mirror of
https://github.com/vacp2p/rfc.vac.dev.git
synced 2026-08-31 12:11:11 +00:00
151 lines
248 KiB
HTML
151 lines
248 KiB
HTML
<!doctype html>
|
||
<html lang="en" dir="ltr" class="docs-wrapper docs-doc-page docs-version-current plugin-docs plugin-id-codex docs-doc-id-raw/codex-block-exchange">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="generator" content="Docusaurus v2.4.1">
|
||
<title data-rh="true">CODEX-BLOCK-EXCHANGE | Vac Research</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://vac.dev/codex/raw/codex-block-exchange"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="image" content="https://vac.dev/_og/82c156aed9e368919af1ca7bea00240f41c664f8.png"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-codex-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-codex-current"><meta data-rh="true" property="og:title" content="CODEX-BLOCK-EXCHANGE | Vac Research"><meta data-rh="true" name="description" content="- Status: raw"><meta data-rh="true" property="og:description" content="- Status: raw"><link data-rh="true" rel="icon" href="/theme/image/favicon.ico"><link data-rh="true" rel="canonical" href="https://vac.dev/codex/raw/codex-block-exchange"><link data-rh="true" rel="alternate" href="https://vac.dev/codex/raw/codex-block-exchange" hreflang="en"><link data-rh="true" rel="alternate" href="https://vac.dev/codex/raw/codex-block-exchange" hreflang="x-default"><link rel="alternate icon" type="image/png" href="/theme/image/favicon.png">
|
||
<link rel="icon" type="image/svg+xml" href="/theme/image/favicon.svg">
|
||
|
||
|
||
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.24/dist/katex.min.css" integrity="sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM" crossorigin="anonymous"><link rel="stylesheet" href="/assets/css/styles.7f69a75a.css">
|
||
<link rel="preload" href="/assets/js/runtime~main.db01e95f.js" as="script">
|
||
<link rel="preload" href="/assets/js/main.7bd63d25.js" as="script">
|
||
<meta property="og:image" content="https://vac.dev/_og/82c156aed9e368919af1ca7bea00240f41c664f8.png"><meta name="twitter:image" content="https://vac.dev/_og/82c156aed9e368919af1ca7bea00240f41c664f8.png"></head>
|
||
<body class="navigation-with-keyboard">
|
||
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"dark")}()</script><div id="__docusaurus">
|
||
<style data-emotion="css-global 3rtehh">.lsd-button{width:auto;cursor:pointer;padding:6px 24px;}.lsd-button--disabled{cursor:default;opacity:0.34;}.lsd-button--large{padding:10px 40px;}.lsd-button--medium{padding:6px 24px;}.lsd-button--small{padding:6px 12px;}.lsd-button:hover:not(.lsd-button--disabled) .lsd-button__text{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-button--with-icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-button__icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;}.lsd-button--large.lsd-button--with-icon{padding:10px 0px 10px 18px;}.lsd-button--large.lsd-button--with-icon .lsd-button__icon{width:42px;}.lsd-button--medium.lsd-button--with-icon{padding:6px 0px 6px 14px;}.lsd-button--medium.lsd-button--with-icon .lsd-button__icon{width:38px;}.lsd-button--small.lsd-button--with-icon{padding:6px 0px 6px 12px;}.lsd-button--small.lsd-button--with-icon .lsd-button__icon{width:34px;}.lsd-button--outlined{background:none;border:1px solid rgb(var(--lsd-border-primary));}.lsd-button--outlined .lsd-button__text{color:rgb(var(--lsd-text-primary));}.lsd-button--filled{background:rgb(var(--lsd-surface-secondary));border:1px solid rgb(var(--lsd-border-primary));}.lsd-button--filled .lsd-button__text{color:rgb(var(--lsd-text-secondary));}</style><style data-emotion="css-global 10bahxd">.lsd-icon-button{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;cursor:pointer;background:none;padding:0;border:1px solid rgb(var(--lsd-border-primary));}.lsd-icon-button--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-icon-button--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-icon-button--disabled{opacity:0.34;cursor:default;}.lsd-icon-button--large{width:40px;height:40px;}.lsd-icon-button--medium{width:32px;height:32px;}.lsd-icon-button--small{width:28px;height:28px;}</style><style data-emotion="css-global icqph9">.lsd-icon-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}.lsd-icon-button-group--outlined .lsd-icon-button:not(:last-child){border-right:none;}</style><style data-emotion="css-global 1f43ub2">body *{font-family:var(--lsd-typography-generic-font-family);}.lsd-typography{color:rgb(var(--lsd-text-primary));}.lsd-typography--sans-serif,.lsd-typography--sans-serif *{font-family:sans-serif;}.lsd-typography--serif,.lsd-typography--serif *{font-family:serif;}.lsd-typography--monospace,.lsd-typography--monospace *{font-family:monospace;}.lsd-typography--display1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display1-fontWeight);font-size:var(--lsd-display1-fontSize);line-height:var(--lsd-display1-lineHeight);}.lsd-typography--display2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display2-fontWeight);font-size:var(--lsd-display2-fontSize);line-height:var(--lsd-display2-lineHeight);}.lsd-typography--display3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display3-fontWeight);font-size:var(--lsd-display3-fontSize);line-height:var(--lsd-display3-lineHeight);}.lsd-typography--display4{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-display4-fontWeight);font-size:var(--lsd-display4-fontSize);line-height:var(--lsd-display4-lineHeight);}h1,.lsd-typography--h1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h1-fontWeight);font-size:var(--lsd-h1-fontSize);line-height:var(--lsd-h1-lineHeight);}h2,.lsd-typography--h2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h2-fontWeight);font-size:var(--lsd-h2-fontSize);line-height:var(--lsd-h2-lineHeight);}h3,.lsd-typography--h3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h3-fontWeight);font-size:var(--lsd-h3-fontSize);line-height:var(--lsd-h3-lineHeight);}h4,.lsd-typography--h4{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h4-fontWeight);font-size:var(--lsd-h4-fontSize);line-height:var(--lsd-h4-lineHeight);}h5,.lsd-typography--h5{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h5-fontWeight);font-size:var(--lsd-h5-fontSize);line-height:var(--lsd-h5-lineHeight);}h6,.lsd-typography--h6{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-h6-fontWeight);font-size:var(--lsd-h6-fontSize);line-height:var(--lsd-h6-lineHeight);}.lsd-typography--subtitle1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle1-fontWeight);font-size:var(--lsd-subtitle1-fontSize);line-height:var(--lsd-subtitle1-lineHeight);}.lsd-typography--subtitle2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle2-fontWeight);font-size:var(--lsd-subtitle2-fontSize);line-height:var(--lsd-subtitle2-lineHeight);}.lsd-typography--subtitle3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle3-fontWeight);font-size:var(--lsd-subtitle3-fontSize);line-height:var(--lsd-subtitle3-lineHeight);}.lsd-typography--subtitle4{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-subtitle4-fontWeight);font-size:var(--lsd-subtitle4-fontSize);line-height:var(--lsd-subtitle4-lineHeight);}body,.lsd-typography--body1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-body1-fontWeight);font-size:var(--lsd-body1-fontSize);line-height:var(--lsd-body1-lineHeight);}.lsd-typography--body2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-body2-fontWeight);font-size:var(--lsd-body2-fontSize);line-height:var(--lsd-body2-lineHeight);}.lsd-typography--body3{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-body3-fontWeight);font-size:var(--lsd-body3-fontSize);line-height:var(--lsd-body3-lineHeight);}label,.lsd-typography--label1{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-label1-fontWeight);font-size:var(--lsd-label1-fontSize);line-height:var(--lsd-label1-lineHeight);}.lsd-typography--label2{color:rgb(var(--lsd-text-primary));font-weight:var(--lsd-label2-fontWeight);font-size:var(--lsd-label2-fontSize);line-height:var(--lsd-label2-lineHeight);}.lsd-typography--primary{color:rgb(var(--lsd-text-primary));}.lsd-typography--secondary{color:rgb(var(--lsd-text-secondary));}input{color:rgb(var(--lsd-text-primary));font-size:var(--lsd-body1-fontSize);font-weight:var(--lsd-body1-fontWeight);}h1,h2,h3,h4,h5,h6,p,span{margin:0;}</style><style data-emotion="css-global 1yxb6i5">.lsd-icon--primary.lsd-icon--filled,.lsd-icon--primary.lsd-icon--filled *{fill:rgb(var(--lsd-icon-primary));}.lsd-icon--primary $.lsd-icon--stroked,.lsd-icon--primary $.lsd-icon--stroked *{fill:rgb(var(--lsd-icon-primary));}.lsd-icon--secondary.lsd-icon--filled,.lsd-icon--secondary.lsd-icon--filled *{fill:rgb(var(--lsd-icon-secondary));}.lsd-icon--secondary $.lsd-icon--stroked,.lsd-icon--secondary $.lsd-icon--stroked *{fill:rgb(var(--lsd-icon-secondary));}</style><style data-emotion="css-global 1hozxbf">.lsd-tab-item{background:rgb(var(--lsd-surface-primary));border:1px solid transparent;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;}.lsd-tab-item:hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-tab-item:not(lsd-tab-item--selected){border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-tab-item--text{overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.lsd-tab-item--icon{margin-left:14px;}.lsd-tab-item--selected{border:1px solid rgb(var(--lsd-border-primary));}.lsd-tab-item--selected:hover{-webkit-text-decoration:none;text-decoration:none;}.lsd-tab-item--with-icon{-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-tab-item--disabled{cursor:default;opacity:0.34;}.lsd-tab-item--disabled:hover{-webkit-text-decoration:none;text-decoration:none;}.lsd-tab-item--small{padding:6px 12px;}.lsd-tab-item--small .lsd-tab-item--icon{margin-left:10px;}.lsd-tab-item--medium{padding:6px 14px;}.lsd-tab-item--medium .lsd-tab-item--icon{margin-left:12px;}.lsd-tab-item--large{padding:10px 18px;}.lsd-tab-item--large .lsd-tab-item--icon{margin-left:14px;}</style><style data-emotion="css-global 1a24j7d">.lsd-tabs{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;overflow:auto;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-tabs>*{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-tabs .lsd-tab-item{border-bottom:none;}.lsd-tabs--full-width{width:100%;-webkit-box-pack:stretch;-ms-flex-pack:stretch;-webkit-justify-content:stretch;justify-content:stretch;}.lsd-tabs--full-width>*{width:100%;-webkit-flex:1 0;-ms-flex:1 0;flex:1 0;}.lsd-tabs{-ms-overflow-style:none;scrollbar-width:none;}.lsd-tabs::-webkit-scrollbar{display:none;}.lsd-tabs__left-scroll-control{left:0;}.lsd-tabs__right-scroll-control{right:0;}.lsd-tabs__right-scroll-control,.lsd-tabs__left-scroll-control{top:0;-webkit-flex:0 1;-ms-flex:0 1;flex:0 1;position:-webkit-sticky;position:sticky;}</style><style data-emotion="css-global 1v7gjjb">.lsd-dropdown-menu{position:absolute;top:0;left:0;opacity:0;visibility:hidden;margin:0;padding:0;box-sizing:border-box;background:rgb(var(--lsd-surface-primary));overflow:auto;border:1px solid rgb(var(--lsd-border-primary));border-top:0;}.lsd-dropdown-menu>div{border:0;}.lsd-dropdown-menu>div:not(:last-child){border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown-menu--open{opacity:1;visibility:visible;}.lsd-dropdown-menu--large{max-height:220px;}.lsd-dropdown-menu--medium{max-height:176px;}.lsd-dropdown-menu--small{max-height:154px;}</style><style data-emotion="css-global hyd3xb">.lsd-dropdown:not(.lsd-dropdown--disabled):not(
|
||
.lsd-dropdown--error
|
||
) .lsd-dropdown__trigger:hover .lsd-dropdown__option-label,.lsd-dropdown:not(.lsd-dropdown--disabled):not(
|
||
.lsd-dropdown--error
|
||
) .lsd-dropdown__trigger:focus .lsd-dropdown__option-label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-dropdown__label{display:block;}.lsd-dropdown__button-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-dropdown__trigger{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;border:none;cursor:pointer;background:none;}.lsd-dropdown__trigger:focus{outline:none;}.lsd-dropdown__option-label{cursor:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}.lsd-dropdown__icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;gap:8px;}.lsd-dropdown__icon{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-dropdown__supporting-text{margin:6px 14px;}.lsd-dropdown--error .lsd-dropdown__option-label{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-dropdown--disabled{opacity:0.34;cursor:initial;}.lsd-dropdown--large{width:208px;}.lsd-dropdown--large.lsd-dropdown--error{width:230px;}.lsd-dropdown--large .lsd-dropdown__label{margin:0 0 6px 18px;}.lsd-dropdown--large .lsd-dropdown__button-container{height:40px;}.lsd-dropdown--large .lsd-dropdown__trigger{padding:10px 0px 10px 18px;}.lsd-dropdown--large .lsd-dropdown__icons{padding:0px 14px;}.lsd-dropdown--medium{width:188px;}.lsd-dropdown--medium.lsd-dropdown--error{width:210px;}.lsd-dropdown--medium .lsd-dropdown__label{margin:0 0 6px 14px;}.lsd-dropdown--medium .lsd-dropdown__button-container{height:32px;}.lsd-dropdown--medium .lsd-dropdown__trigger{padding:6px 0px 6px 14px;}.lsd-dropdown--medium .lsd-dropdown__icons{padding:0px 12px;}.lsd-dropdown--small{width:164px;}.lsd-dropdown--small.lsd-dropdown--error{width:186px;}.lsd-dropdown--small .lsd-dropdown__label{margin:0 0 6px 12px;}.lsd-dropdown--small .lsd-dropdown__button-container{height:28px;}.lsd-dropdown--small .lsd-dropdown__trigger{padding:6px 0px 6px 12px;}.lsd-dropdown--small .lsd-dropdown__icons{padding:0px 10px;}.lsd-dropdown--outlined .lsd-dropdown__button-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown--underlined .lsd-dropdown__button-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global w2g5fy">.lsd-dropdown-item{width:100%;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid rgb(var(--lsd-border-primary));}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled){cursor:pointer;}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):hover,.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):focus{outline:none;}.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):hover .lsd-dropdown-item__label,.lsd-dropdown-item:not(.lsd-dropdown-item--disabled):focus .lsd-dropdown-item__label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-dropdown-item__label{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.lsd-dropdown-item--disabled{opacity:0.34;}.lsd-dropdown-item__icon{margin-right:18px;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-dropdown-item--small{padding:5px 9px;height:28px;}.lsd-dropdown-item--medium{padding:5px 11px;height:32px;}.lsd-dropdown-item--large{padding:5px 13px;height:40px;}</style><style data-emotion="css-global ww9kgc">.lsd-breadcrumb__list{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;list-style-type:none;margin:0;padding:0;}.lsd-breadcrumb--disabled .lsd-breadcrumb__list{opacity:0.34;cursor:initial;pointer-events:none;}.lsd-breadcrumb__dropdown-menu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;overflow:auto;border:1px solid rgb(var(--lsd-border-primary));margin-top:10px;position:absolute;width:auto!important;}.lsd-breadcrumb__dropdown-menu>li{cursor:pointer;}.lsd-breadcrumb__dropdown-menu>li:not(:last-child){border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-breadcrumb__dropdown-menu>li:hover,.lsd-breadcrumb__dropdown-menu>li:focus{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgb(var(--lsd-border-primary));}.lsd-breadcrumb__dropdown-menu li>a{width:164px;padding:5px 11px;}</style><style data-emotion="css-global 4gvini">.lsd-breadcrumb-item{list-style-type:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-breadcrumb__list>li:not(:last-child)::after{display:inline-block;margin-inline:12px;content:'/';}.lsd-breadcrumb-item__link{-webkit-text-decoration:none;text-decoration:none;cursor:pointer;}.lsd-breadcrumb-item--outlined{padding:3px 11px;border:1px solid rgb(var(--lsd-border-primary));}.lsd-breadcrumb:not(.lsd-breadcrumb--disabled) .lsd-breadcrumb-item__link:hover,.lsd-breadcrumb:not(.lsd-breadcrumb--disabled) .lsd-breadcrumb-item__link:focus{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 1cwg3oc">.lsd-card{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-card>.lsd-card-header{margin-bottom:-1px;}</style><style data-emotion="css-global v7d76i">.lsd-card-header{box-sizing:border-box;padding:10px 18px;text-align:center;border:1px solid rgb(var(--lsd-border-primary));}.lsd-card-header__title{overflow:hidden;word-break:break-all;}.lsd-card-header--large{padding:10px 18px;}.lsd-card-header--medium{padding:6px 14px;}.lsd-card-header--small{padding:6px 12px;}</style><style data-emotion="css-global 1txgafh">.lsd-card-body{box-sizing:border-box;padding:14px 22px;border:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global kzy52c">.lsd-tag{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;box-sizing:border-box;border:1px solid rgb(var(--lsd-icon-primary));}.lsd-tag:hover,.lsd-tag:focus{-webkit-text-decoration:underline;text-decoration:underline;cursor:pointer;}.lsd-badge--large{padding:3px 11px;gap:12px;height:28px;}.lsd-badge--small{padding:3px 7px;gap:8px;height:24px;}.lsd-tag--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-tag--filled .lsd-tag__label{color:rgb(var(--lsd-text-secondary));}.lsd-tag--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-tag--outlined{color:rgb(var(--lsd-text-primary));}.lsd-tag--disabled{opacity:0.3;cursor:initial;pointer-events:none;}</style><style data-emotion="css-global 4wy0ub">.lsd-text-field{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-text-field__input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-text-field--disabled{opacity:0.34;}.lsd-text-field__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;width:100%;}.lsd-text-field__input:hover{outline:none;}.lsd-text-field__input::-webkit-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field__input::-moz-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field__input:-ms-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field__input::placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-text-field--error .lsd-text-field__input{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-text-field__supporting-text{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-text-field--large{width:208px;}.lsd-text-field--large>*{padding:10px 14px 10px 18px;}.lsd-text-field--medium{width:188px;}.lsd-text-field--medium>*{padding:6px 12px 6px 14px;}.lsd-text-field--small{width:164px;}.lsd-text-field--small>*{padding:6px 10px 6px 12px;}.lsd-text-field__label{padding-top:0;padding-bottom:6px;}.lsd-text-field__supporting-text{padding-bottom:0;padding-top:6px;}.lsd-text-field--outlined .lsd-text-field__input-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-text-field--underlined .lsd-text-field__input-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-text-field__clear-button{padding:0;width:auto;height:auto;margin:0;border:0;}</style><style data-emotion="css-global uhig7c">.lsd-checkbox{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-checkbox__input{opacity:0;position:absolute;left:0;top:0;padding:0;margin:0;width:100%;height:100%;}.lsd-checkbox:not(.lsd-checkbox--disabled):hover,.lsd-checkbox:not(.lsd-checkbox--disabled).lsd-checkbox--focused{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-checkbox:not(.lsd-checkbox--disabled) .lsd-checkbox__input{cursor:pointer;}.lsd-checkbox--disabled{opacity:0.34;}.lsd-checkbox__label{margin-left:18px;}.lsd-checkbox--large .lsd-checkbox__label{margin-left:18px;}.lsd-checkbox--medium .lsd-checkbox__label{margin-left:14px;}.lsd-checkbox--small .lsd-checkbox__label{margin-left:12px;}</style><style data-emotion="css-global txommo">.lsd-autocomplete{box-sizing:border-box;}.lsd-autocomplete__label{display:block;}.lsd-autocomplete__input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-autocomplete--disabled{opacity:0.34;}.lsd-autocomplete__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;width:100%;}.lsd-autocomplete__input:hover{outline:none;}.lsd-autocomplete__input::-webkit-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__input::-moz-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__input:-ms-input-placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__input::placeholder{color:rgb(var(--lsd-text-primary));opacity:0.3;}.lsd-autocomplete__icon{cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-autocomplete--error{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-autocomplete--large{width:208px;}.lsd-autocomplete--large .lsd-autocomplete__label{margin:0 0 6px 18px;}.lsd-autocomplete--large .lsd-autocomplete__input-container{height:40px;}.lsd-autocomplete--large .lsd-autocomplete__input{padding:9px 17px;}.lsd-autocomplete--large .lsd-autocomplete__icon{padding:12px 13px;}.lsd-autocomplete--medium{width:188px;}.lsd-autocomplete--medium .lsd-autocomplete__label{margin:0 0 6px 14px;}.lsd-autocomplete--medium .lsd-autocomplete__input-container{height:32px;}.lsd-autocomplete--medium .lsd-autocomplete__input{padding:5px 13px;}.lsd-autocomplete--medium .lsd-autocomplete__icon{padding:8px 11px;}.lsd-autocomplete--small{width:164px;}.lsd-autocomplete--small .lsd-autocomplete__label{margin:0 0 6px 12px;}.lsd-autocomplete--small .lsd-autocomplete__input-container{height:28px;}.lsd-autocomplete--small .lsd-autocomplete__input{padding:5px 11px;}.lsd-autocomplete--small .lsd-autocomplete__icon{padding:6px 9px;}.lsd-autocomplete--outlined .lsd-autocomplete__input-container{border:1px solid rgb(var(--lsd-border-primary));}.lsd-autocomplete--underlined .lsd-autocomplete__input-container{border:1px solid transparent;border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-autocomplete__dropdown-item-placeholder{opacity:0.5;white-space:pre;}</style><style data-emotion="css-global quxxm6">.lsd-quote{color:rgb(var(--lsd-text-primary));white-space:pre-wrap;}.lsd-quote--indented-inline{border-left:1px solid rgb(var(--lsd-border-primary));padding:4px 8px 4px 28px;}.lsd-quote--parentheses{padding:0px;text-align:center;}.lsd-quote--parentheses::before{content:'***';}.lsd-quote--parentheses::after{content:'***';}</style><style data-emotion="css-global a49t4h">.lsd-collapse{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-collapse--open .lsd-collapse__content{border-top:1px solid transparent;}.lsd-collapse__content{border:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 12ppw0q">.lsd-collapse-header{box-sizing:border-box;}.lsd-collapse-header:not(.lsd-collapse-header--disabled) .lsd-collapse-header__trigger:hover .lsd-collapse-header__label{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-collapse-header__trigger{width:100%;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;cursor:pointer;background:none;border:1px solid rgb(var(--lsd-border-primary));}.lsd-collapse-header__trigger:focus{outline:none;}.lsd-collapse-header__label{cursor:inherit;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:auto;}.lsd-collapse-header__icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:end;-ms-flex-pack:end;-webkit-justify-content:flex-end;justify-content:flex-end;}.lsd-collapse-header__icon{margin-right:8px;}.lsd-collapse-header--disabled .lsd-collapse-header__trigger{opacity:0.34;cursor:initial;}.lsd-collapse-header--large .lsd-collapse-header__trigger{width:299px;height:40px;padding:9px 17px;}.lsd-collapse-header--medium .lsd-collapse-header__trigger{width:270px;height:32px;padding:5px 13px;}.lsd-collapse-header--small .lsd-collapse-header__trigger{width:235px;height:28px;padding:5px 11px;}</style><style data-emotion="css-global dixc0i">.lsd-checkbox-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:6px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-checkbox-group__label{margin-bottom:6px;}</style><style data-emotion="css-global q2n2hz">.lsd-badge{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;border:1px solid rgb(var(--lsd-icon-primary));border-radius:20px;}.lsd-badge:hover,.lsd-badge:focus{-webkit-text-decoration:underline;text-decoration:underline;cursor:pointer;}.lsd-badge--large{padding:3px 11px;gap:12px;height:28px;}.lsd-badge--small{padding:3px 7px;gap:8px;height:24px;}.lsd-badge--filled{background-color:rgb(var(--lsd-icon-primary));}.lsd-badge--filled .lsd-badge__label{color:rgb(var(--lsd-text-secondary));}.lsd-badge--filled svg{--lsd-icon-primary:var(--lsd-icon-secondary);}.lsd-badge--outlined{color:rgb(var(--lsd-text-primary));}.lsd-badge--disabled{opacity:0.3;cursor:initial;pointer-events:none;}</style><style data-emotion="css-global rlst54">.lsd-radio-button{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-radio-button__input{opacity:0;position:absolute;left:0;top:0;padding:0;margin:0;width:100%;height:100%;}.lsd-radio-button:not(.lsd-radio-button--disabled):hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-radio-button:not(.lsd-radio-button--disabled) .lsd-radio-button__input{cursor:pointer;}.lsd-radio-button--disabled{opacity:0.34;}.lsd-radio-button__label{margin-left:18px;}.lsd-radio-button--large .lsd-radio-button__label{margin-left:18px;}.lsd-radio-button--medium .lsd-radio-button__label{margin-left:14px;}.lsd-radio-button--small .lsd-radio-button__label{margin-left:12px;}</style><style data-emotion="css-global mo7h6o">.lsd-radio-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;gap:6px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-radio-button-group__label{margin-bottom:6px;}</style><style data-emotion="css-global amncrr">.lsd-table{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-table>.lsd-table-header{margin-bottom:-1px;}</style><style data-emotion="css-global 1fkbozr">.lsd-table-header{box-sizing:border-box;border:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 1fb1r54">.lsd-table-body table{border-collapse:collapse;text-align:center;table-layout:fixed;width:100%;height:auto;}.lsd-table-body table tr:first-of-type td label:has(input[type='radio']){display:none;}.lsd-table-body__toolbar{box-sizing:border-box;padding:10px;border:1px solid rgb(var(--lsd-border-primary));border-bottom:none;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}</style><style data-emotion="css-global 607rj8">.lsd-table-item{border:1px solid rgb(var(--lsd-border-primary));}.lsd-table-item:has(> label){width:40px;}.lsd-table-item:has(> label) input{position:relative;width:14px;height:14px;margin:auto;}.lsd-table-item:has(> label) span{margin-left:14px!important;}.lsd-table-item--large{padding:10px;}.lsd-table-item--medium{padding:6px 8px;}.lsd-table-item--small{padding:6px;}</style><style data-emotion="css-global 1vlh57l">.lsd-table-row{-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}</style><style data-emotion="css-global 1fw5y3v">.lsd-number-input{width:auto;box-sizing:border-box;}.lsd-number-input__main-container:hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-number-input--error .lsd-number-input__main-container{-webkit-text-decoration:line-through;text-decoration:line-through;}.lsd-number-input__label{display:block;}.lsd-number-input__plus-minus-icons{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-number-input__input-container{box-sizing:border-box;border:1px solid rgb(var(--lsd-border-primary));border-left:0px;border-right:0px;}.lsd-number-input__error-icon{cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:10px 8px;}.lsd-number-input__input-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-number-input--disabled{opacity:0.34;}.lsd-number-input__main-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-number-input__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;text-align:center;padding:0 4px;}.lsd-number-input__input::-webkit-inner-spin-button{display:none;-webkit-appearance:none;}.lsd-number-input__input:hover{outline:none;}.lsd-number-input__supporting-text{position:absolute;}.lsd-number-input--large .lsd-number-input__label{margin:0 0 6px 18px;}.lsd-number-input--large .lsd-number-input__input-container{height:40px;}.lsd-number-input--large .lsd-number-input__input{width:62px;}.lsd-number-input--large .lsd-number-input__plus-minus-icons{height:40px;width:40px;}.lsd-number-input--large .lsd-number-input__supporting-text{margin:6px 18px 0 18px;}.lsd-number-input--medium .lsd-number-input__label{margin:0 0 6px 14px;}.lsd-number-input--medium .lsd-number-input__input-container{height:32px;}.lsd-number-input--medium .lsd-number-input__input{width:58px;}.lsd-number-input--medium .lsd-number-input__plus-minus-icons{height:32px;width:32px;}.lsd-number-input--medium .lsd-number-input__supporting-text{margin:6px 14px 0 14px;}.lsd-number-input--small .lsd-number-input__label{margin:0 0 6px 12px;}.lsd-number-input--small .lsd-number-input__input-container{height:28px;}.lsd-number-input--small .lsd-number-input__input{width:50px;}.lsd-number-input--small .lsd-number-input__plus-minus-icons{height:28px;width:28px;}.lsd-number-input--small .lsd-number-input__supporting-text{margin:6px 12px 0 12px;}</style><style data-emotion="css-global 12rmo7o">.lsd-modal{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;position:fixed;top:0;left:0;right:0;bottom:0;background-color:rgba(0, 0, 0, 0.5);display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;z-index:9999;}.lsd-modal__container{position:relative;background:rgb(var(--lsd-surface-primary));padding:20px;max-width:90%;box-sizing:border-box;border:1px solid rgb(var(--lsd-border-primary));}.lsd-modal__header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-modal__close-icon{position:absolute;top:8px;right:8px;cursor:pointer;}.lsd-modal__title-and-subtitle-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;}.lsd-modal--large .lsd-modal__container{min-width:960px;}.lsd-modal--medium .lsd-modal__container{min-width:768px;}.lsd-modal--small .lsd-modal__container{min-width:614px;}.lsd-modal--extra-small .lsd-modal__container{min-width:490px;}</style><style data-emotion="css-global 1k7gzc">.lsd-modal-footer{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}</style><style data-emotion="css-global 1b9t8so">.lsd-modal-body{margin:18px 0;}</style><style data-emotion="css-global dyud2a">.lsd-date-picker{width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;}.lsd-date-picker__calendar{border-top:none!important;}.lsd-date-picker--large .lsd-date-field--large{width:318px;}.lsd-date-picker--medium .lsd-date-field--medium{width:290px;}.lsd-date-picker--small .lsd-date-field--small{width:262px;}</style><style data-emotion="css-global olq3nk">.lsd-date-field{width:auto;box-sizing:border-box;}.lsd-date-field__label{display:block;}.lsd-date-field__input-container__icon{position:absolute;right:0;cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:rgb(var(--lsd-surface-primary));}.lsd-date-field__input-container__icon:focus{background:blue;background-color:pink;border:1px solid rgb(var(--lsd-border-primary));}.lsd-date-field__input-container__no-icon{position:absolute;right:0;background-color:rgb(var(--lsd-surface-primary));padding:12px;}.lsd-date-field--outlined{border:1px solid rgb(var(--lsd-border-primary));}.lsd-date-field--underlined{border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-date-field__input-container{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-date-field--disabled{opacity:0.34;}.lsd-date-field__input-container__input{border:none;outline:none;font-size:14px;color:rgb(var(--lsd-text-primary));background:none;width:100%;opacity:0.4;-webkit-transition:opacity 0.2s ease-in-out;transition:opacity 0.2s ease-in-out;}.lsd-date-field__input-container__input::-webkit-inner-spin-button,.lsd-date-field__input-container__input::-webkit-calendar-picker-indicator{display:none;-webkit-appearance:none;}.lsd-date-field__input-container__input:hover{outline:none;}.lsd-date-field__supporting-text{position:absolute;}.lsd-date-field--large{width:208px;}.lsd-date-field--large .lsd-date-field__label{margin:0 0 6px 18px;}.lsd-date-field--large .lsd-date-field__input-container{height:40px;}.lsd-date-field--large .lsd-date-field__input-container__input{padding:9px 0px 9px 17px;}.lsd-date-field--large .lsd-date-field__input-container__icon{padding:12px 13px;}.lsd-date-field--large .lsd-date-field__supporting-text{margin:6px 18px 0 18px;}.lsd-date-field--medium{width:188px;}.lsd-date-field--medium .lsd-date-field__label{margin:0 0 6px 14px;}.lsd-date-field--medium .lsd-date-field__input-container{height:32px;}.lsd-date-field--medium .lsd-date-field__input-container__input{padding:5px 11px 5px 13px;}.lsd-date-field--medium .lsd-date-field__input-container__icon{padding:8px 11px;}.lsd-date-field--medium .lsd-date-field__supporting-text{margin:6px 14px 0 14px;}.lsd-date-field--small{width:164px;}.lsd-date-field--small .lsd-date-field__label{margin:0 0 6px 12px;}.lsd-date-field--small .lsd-date-field__input-container{height:28px;}.lsd-date-field--small .lsd-date-field__input-container__input{padding:5px 9px 5px 11px;font-size:12px;}.lsd-date-field--small .lsd-date-field__input-container__icon{padding:6px 9px;}.lsd-date-field--small .lsd-date-field__supporting-text{margin:6px 12px 0 12px;}.lsd-date-field__input-container__input:invalid,.lsd-date-field__input-container__input--filled{color:rgb(var(--lsd-border-primary));opacity:1;}.lsd-date-field--error .lsd-date-field__input-container__input::-webkit-datetime-edit-year-field,.lsd-date-field--error .lsd-date-field__input-container__input::-webkit-datetime-edit-month-field,.lsd-date-field--error .lsd-date-field__input-container__input::-webkit-datetime-edit-day-field{-webkit-text-decoration:line-through;text-decoration:line-through;}@supports not selector(::-webkit-datetime-edit-day-field){.lsd-date-field--error .lsd-date-field__input-container__input{-webkit-text-decoration:line-through;text-decoration:line-through;}}</style><style data-emotion="css-global 1gjtao4">.lsd-calendar{border:1px solid rgb(var(--lsd-border-primary));visibility:hidden;position:absolute!important;top:0;left:0;opacity:0;visibility:hidden;margin:0;padding:0;box-sizing:border-box;background:rgb(var(--lsd-surface-primary));-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.lsd-calendar-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding:8px;}.lsd-calendar--open{opacity:1;visibility:visible;}.lsd-calendar-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:32px;margin-bottom:8px;}.lsd-calendar__week_day{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;aspect-ratio:1/1;margin-bottom:4px;}.lsd-calendar__change-year{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:2px 0xp 2px 8px;gap:6px;border:1px solid transparent;}.lsd-calendar__change-year--active .lsd-calendar__year-and-icon{border:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar__change-year-icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:pointer;border:none;}.lsd-calendar-month{margin-right:8px;}.lsd-calendar__month-and-year{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;}.lsd-calendar-day__container{cursor:pointer;background:transparent;position:relative;box-sizing:border-box;border:1px solid transparent;}.lsd-calendar-day{aspect-ratio:1/1;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}.lsd-calendar-day:hover{cursor:pointer;-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgb(var(--lsd-border-primary));}.lsd-calendar-day label:hover{cursor:pointer;}.lsd-calendar-day--selected{border:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar-day--disabled{opacity:0.3;cursor:default;}.lsd-calendar-day__today_indicator{position:absolute;left:50%;-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);bottom:2px;}.lsd-calendar--disabled{pointer-events:none;border:1px solid rgba(var(--lsd-border-primary), 0.3);}.lsd-calendar--disabled label{opacity:0.3;}.lsd-calendar--disabled .lsd-calendar__button{opacity:0.3;}.lsd-calendar--disabled .lsd-calendar-day--selected{opacity:0.3;}.lsd-calendar__button{border:1px solid rgb(var(--lsd-border-primary));cursor:pointer;background:transparent;width:32px;height:32px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;position:absolute;}.lsd-calendar__next-month-button{top:8px;right:8px;}.lsd-calendar__previous-month-button{top:8px;left:8px;}.lsd-calendar-day--border-left{border-left:1px double rgb(var(--lsd-border-primary));}.lsd-calendar-day--border-right{border-right:1px double rgb(var(--lsd-border-primary));}.lsd-calendar-day--border-left-and-right{border-left:1px double rgb(var(--lsd-border-primary));border-right:1px double rgb(var(--lsd-border-primary));}.lsd-calendar-day--border-top-and-bottom{border-top:1px double rgb(var(--lsd-border-primary));border-bottom:1px double rgb(var(--lsd-border-primary));}.lsd-calendar__month-table{border-collapse:collapse;}.lsd-calendar__year-dropdown{box-sizing:border-box;position:absolute;top:100%;left:0;max-height:200px;overflow-y:auto;width:100%;border:1px solid rgb(var(--lsd-border-primary));border-top:none;z-index:1;}.lsd-calendar__year-dropdown .lsd-calendar-year{border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar__year-dropdown--hidden{visibility:hidden;}.lsd-calendar-year{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;cursor:pointer;-webkit-transition:background-color 0.2s;transition:background-color 0.2s;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:rgb(var(--lsd-surface-primary));}.lsd-calendar-year:hover{-webkit-text-decoration:underline;text-decoration:underline;}.lsd-calendar__year-and-icon{border:1px solid rgb(var(--lsd-border-primary));}.lsd-calendar--large .lsd-calendar-year{padding:6px 0px 6px 14px;}.lsd-calendar--large .lsd-calendar__change-year-icon-container{width:32px;}.lsd-calendar--medium .lsd-calendar-year{padding:6px 0px 6px 12px;}.lsd-calendar--medium .lsd-calendar__change-year-icon-container{width:28px;}.lsd-calendar--small .lsd-calendar-year{padding:6px 0px 6px 12px;}.lsd-calendar--small .lsd-calendar__change-year-icon-container{width:28px;}</style><style data-emotion="css-global dlrd7d">.lsd-toast{box-sizing:border-box;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:rgb(var(--lsd-surface-primary));border:1px solid rgb(var(--lsd-border-primary));padding:8px;height:-webkit-fit-content;height:-moz-fit-content;height:fit-content;}.lsd-toast__inline-button-container{-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;}.lsd-toast__column-button-container{margin-top:18px;margin-bottom:6px;}.lsd-toast__inline-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}.lsd-toast__column-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;}.lsd-toast__text-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;color:rgb(var(--lsd-text-secondary));padding-left:12px;}.lsd-toast__title{position:relative;}.lsd-toast__information{margin-top:4px;}.lsd-toast__button-container{min-height:28px;min-width:60px;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;padding:0px 12px;}.lsd-toast__close-button{margin-bottom:auto;-webkit-flex-shrink:0;-ms-flex-negative:0;flex-shrink:0;height:28px;width:28px;margin-left:auto;}.lsd-toast__column-icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;margin-bottom:auto;position:relative;top:4px;padding-left:4px;}.lsd-toast__inline-icon-container{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;padding-left:4px;}.lsd-toast__icon{position:relative;}.lsd-toast--large{width:364px;}.lsd-toast--medium{width:336px;}.lsd-toast--small{width:296px;}.lsd-toast--small .lsd-toast__icon{top:0px;}</style><style data-emotion="css-global 5wlfwk">.lsd-toast-provider__toast-container{position:fixed;-webkit-transition:all 230ms cubic-bezier(0.21, 1.02, 0.73, 1);transition:all 230ms cubic-bezier(0.21, 1.02, 0.73, 1);z-index:9999;}.lsd-toast-provider__toast--top-left,.lsd-toast-provider__toast--top-center,.lsd-toast-provider__toast--top-right{top:0;}.lsd-toast-provider__toast--bottom-left,.lsd-toast-provider__toast--bottom-center,.lsd-toast-provider__toast--bottom-right{bottom:0;}.lsd-toast-provider__toast--top-center,.lsd-toast-provider__toast--bottom-center{left:50%;}.lsd-toast-provider__toast--top-right,.lsd-toast-provider__toast--bottom-right{right:0;}</style><style data-emotion="css-global 9yw6e1">.lsd-button-group{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;}.lsd-button-group >*:not(:last-child).lsd-button--outlined,.lsd-button-group >*:not(:last-child) .lsd-button--outlined{border-right:none;}</style><style data-emotion="css-global 17u9w7w">.lsd-date-range-picker{box-sizing:border-box;}.lsd-date-range-picker .lsd-date-field--outlined{border:none;}.lsd-date-range-picker .lsd-date-field__input-container__icon{padding:8px;}.lsd-date-range-picker__label{display:block;}.lsd-date-range-picker__input-container{box-sizing:border-box;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px solid transparent;}.lsd-date-picker__calendar{border-top:none!important;}.lsd-date-picker__calendar .lsd-tooltip-base__arrow-tip{-webkit-transition:left 0.2s ease-in-out;transition:left 0.2s ease-in-out;}.lsd-date-range-picker--calendar-open .lsd-date-range-picker__input-container{border-bottom:1px solid rgb(var(--lsd-border-primary));}.lsd-date-range-picker__icon{cursor:pointer;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;padding:0 10px;}.lsd-date-range-picker--disabled{opacity:0.3;}.lsd-date-range-picker__supporting-text{position:absolute;}.lsd-date-range-picker--large{width:318px;}.lsd-date-range-picker--large .lsd-date-field--large{width:156px;}.lsd-date-range-picker--large .lsd-date-field__input-container__input{padding-right:0;}.lsd-date-range-picker--large .lsd-date-field__input-container__icon{padding:11px 12px;}.lsd-date-range-picker--large .lsd-date-range-picker__label{margin:0 0 6px 18px;}.lsd-date-range-picker--large .lsd-date-range-picker__input-container{height:40px;}.lsd-date-range-picker--large .lsd-date-range-picker__supporting-text{margin:6px 18px 0 18px;}.lsd-date-range-picker--medium{width:290px;}.lsd-date-range-picker--medium .lsd-date-field--medium{width:142px;}.lsd-date-range-picker--medium .lsd-date-field__input-container__input{padding-right:0;}.lsd-date-range-picker--medium .lsd-date-field__input-container__icon{padding:7px 8px;}.lsd-date-range-picker--medium .lsd-date-range-picker__label{margin:0 0 6px 14px;}.lsd-date-range-picker--medium .lsd-date-range-picker__input-container{height:32px;}.lsd-date-range-picker--medium .lsd-date-range-picker__supporting-text{margin:6px 14px 0 14px;}.lsd-date-range-picker--small{width:262px;}.lsd-date-range-picker--small .lsd-date-field--small{width:128px;}.lsd-date-range-picker--small .lsd-date-field__input-container__input{padding-right:0;}.lsd-date-range-picker--small .lsd-date-field__input-container__icon{padding:5px 7px;}.lsd-date-range-picker--small .lsd-date-range-picker__label{margin:0 0 6px 12px;}.lsd-date-range-picker--small .lsd-date-range-picker__input-container{height:28px;}.lsd-date-range-picker--small .lsd-date-range-picker__supporting-text{margin:6px 12px 0 12px;}.lsd-date-range-picker__separator{margin-left:3px;width:1px;height:100%;}.lsd-date-range-picker__separator{border-left:1px solid transparent;}.lsd-date-range-picker--outlined{border:1px solid rgb(var(--lsd-border-primary));}.lsd-date-range-picker--outlined .lsd-date-range-picker__separator{border-left:1px solid rgb(var(--lsd-border-primary));}</style><style data-emotion="css-global 19d282h">.lsd-tooltip-base{border:1px solid rgb(var(--lsd-border-primary));position:relative;}.lsd-tooltip-base__arrow-tip{border:1px solid rgb(var(--lsd-border-primary));position:absolute;background:rgb(var(--lsd-surface-primary));}.lsd-tooltip-base__content{background:rgb(var(--lsd-surface-primary));width:100%;height:100%;position:relative;z-index:1;}</style><style data-emotion="css-global js1ujt">html:not([data-theme]){--lsd-display1-fontSize:5.5rem;--lsd-display1-fontWeight:normal;--lsd-display1-lineHeight:6rem;--lsd-display2-fontSize:4rem;--lsd-display2-fontWeight:normal;--lsd-display2-lineHeight:4.5rem;--lsd-display3-fontSize:3.5rem;--lsd-display3-fontWeight:normal;--lsd-display3-lineHeight:4rem;--lsd-display4-fontSize:3rem;--lsd-display4-fontWeight:normal;--lsd-display4-lineHeight:3.5rem;--lsd-h1-fontSize:2.5rem;--lsd-h1-fontWeight:normal;--lsd-h1-lineHeight:3rem;--lsd-h2-fontSize:2rem;--lsd-h2-fontWeight:normal;--lsd-h2-lineHeight:2.5rem;--lsd-h3-fontSize:1.75rem;--lsd-h3-fontWeight:normal;--lsd-h3-lineHeight:2.25rem;--lsd-h4-fontSize:1.5rem;--lsd-h4-fontWeight:normal;--lsd-h4-lineHeight:2rem;--lsd-h5-fontSize:1.25rem;--lsd-h5-fontWeight:normal;--lsd-h5-lineHeight:1.75rem;--lsd-h6-fontSize:1rem;--lsd-h6-fontWeight:normal;--lsd-h6-lineHeight:1.5rem;--lsd-subtitle1-fontSize:1.125rem;--lsd-subtitle1-fontWeight:normal;--lsd-subtitle1-lineHeight:1.5rem;--lsd-subtitle2-fontSize:1rem;--lsd-subtitle2-fontWeight:normal;--lsd-subtitle2-lineHeight:1.5rem;--lsd-subtitle3-fontSize:0.875rem;--lsd-subtitle3-fontWeight:normal;--lsd-subtitle3-lineHeight:1.25rem;--lsd-subtitle4-fontSize:0.75rem;--lsd-subtitle4-fontWeight:normal;--lsd-subtitle4-lineHeight:1rem;--lsd-body1-fontSize:1rem;--lsd-body1-fontWeight:normal;--lsd-body1-lineHeight:1.5rem;--lsd-body2-fontSize:0.875rem;--lsd-body2-fontWeight:normal;--lsd-body2-lineHeight:1.25rem;--lsd-body3-fontSize:0.75rem;--lsd-body3-fontWeight:normal;--lsd-body3-lineHeight:1rem;--lsd-label1-fontSize:0.875rem;--lsd-label1-fontWeight:normal;--lsd-label1-lineHeight:1.25rem;--lsd-label2-fontSize:0.75rem;--lsd-label2-fontWeight:normal;--lsd-label2-lineHeight:1rem;--lsd-typography-generic-font-family:sans-serif;--lsd-theme-primary:0,0,0;--lsd-theme-secondary:255,255,255;--lsd-surface-primary:255,255,255;--lsd-surface-secondary:0,0,0;--lsd-border-primary:0,0,0;--lsd-border-secondary:255,255,255;--lsd-icon-primary:0,0,0;--lsd-icon-secondary:255,255,255;--lsd-text-primary:0,0,0;--lsd-text-secondary:255,255,255;--lsd-text-tertiary:0,0,0,0.34;--lsd-spacing-4:4px;--lsd-spacing-8:8px;--lsd-spacing-16:16px;--lsd-spacing-24:24px;--lsd-spacing-32:32px;--lsd-spacing-40:40px;--lsd-spacing-64:64px;--lsd-spacing-80:80px;--lsd-spacing-96:96px;--lsd-spacing-120:120px;}html[data-theme='light']{--lsd-display1-fontSize:5.5rem;--lsd-display1-fontWeight:normal;--lsd-display1-lineHeight:6rem;--lsd-display2-fontSize:4rem;--lsd-display2-fontWeight:normal;--lsd-display2-lineHeight:4.5rem;--lsd-display3-fontSize:3.5rem;--lsd-display3-fontWeight:normal;--lsd-display3-lineHeight:4rem;--lsd-display4-fontSize:3rem;--lsd-display4-fontWeight:normal;--lsd-display4-lineHeight:3.5rem;--lsd-h1-fontSize:2.5rem;--lsd-h1-fontWeight:normal;--lsd-h1-lineHeight:3rem;--lsd-h2-fontSize:2rem;--lsd-h2-fontWeight:normal;--lsd-h2-lineHeight:2.5rem;--lsd-h3-fontSize:1.75rem;--lsd-h3-fontWeight:normal;--lsd-h3-lineHeight:2.25rem;--lsd-h4-fontSize:1.5rem;--lsd-h4-fontWeight:normal;--lsd-h4-lineHeight:2rem;--lsd-h5-fontSize:1.25rem;--lsd-h5-fontWeight:normal;--lsd-h5-lineHeight:1.75rem;--lsd-h6-fontSize:1rem;--lsd-h6-fontWeight:normal;--lsd-h6-lineHeight:1.5rem;--lsd-subtitle1-fontSize:1.125rem;--lsd-subtitle1-fontWeight:normal;--lsd-subtitle1-lineHeight:1.5rem;--lsd-subtitle2-fontSize:1rem;--lsd-subtitle2-fontWeight:normal;--lsd-subtitle2-lineHeight:1.5rem;--lsd-subtitle3-fontSize:0.875rem;--lsd-subtitle3-fontWeight:normal;--lsd-subtitle3-lineHeight:1.25rem;--lsd-subtitle4-fontSize:0.75rem;--lsd-subtitle4-fontWeight:normal;--lsd-subtitle4-lineHeight:1rem;--lsd-body1-fontSize:1rem;--lsd-body1-fontWeight:normal;--lsd-body1-lineHeight:1.5rem;--lsd-body2-fontSize:0.875rem;--lsd-body2-fontWeight:normal;--lsd-body2-lineHeight:1.25rem;--lsd-body3-fontSize:0.75rem;--lsd-body3-fontWeight:normal;--lsd-body3-lineHeight:1rem;--lsd-label1-fontSize:0.875rem;--lsd-label1-fontWeight:normal;--lsd-label1-lineHeight:1.25rem;--lsd-label2-fontSize:0.75rem;--lsd-label2-fontWeight:normal;--lsd-label2-lineHeight:1rem;--lsd-typography-generic-font-family:sans-serif;--lsd-theme-primary:0,0,0;--lsd-theme-secondary:255,255,255;--lsd-surface-primary:255,255,255;--lsd-surface-secondary:0,0,0;--lsd-border-primary:0,0,0;--lsd-border-secondary:255,255,255;--lsd-icon-primary:0,0,0;--lsd-icon-secondary:255,255,255;--lsd-text-primary:0,0,0;--lsd-text-secondary:255,255,255;--lsd-text-tertiary:0,0,0,0.34;--lsd-spacing-4:4px;--lsd-spacing-8:8px;--lsd-spacing-16:16px;--lsd-spacing-24:24px;--lsd-spacing-32:32px;--lsd-spacing-40:40px;--lsd-spacing-64:64px;--lsd-spacing-80:80px;--lsd-spacing-96:96px;--lsd-spacing-120:120px;}html[data-theme='dark']{--lsd-display1-fontSize:5.5rem;--lsd-display1-fontWeight:normal;--lsd-display1-lineHeight:6rem;--lsd-display2-fontSize:4rem;--lsd-display2-fontWeight:normal;--lsd-display2-lineHeight:4.5rem;--lsd-display3-fontSize:3.5rem;--lsd-display3-fontWeight:normal;--lsd-display3-lineHeight:4rem;--lsd-display4-fontSize:3rem;--lsd-display4-fontWeight:normal;--lsd-display4-lineHeight:3.5rem;--lsd-h1-fontSize:2.5rem;--lsd-h1-fontWeight:normal;--lsd-h1-lineHeight:3rem;--lsd-h2-fontSize:2rem;--lsd-h2-fontWeight:normal;--lsd-h2-lineHeight:2.5rem;--lsd-h3-fontSize:1.75rem;--lsd-h3-fontWeight:normal;--lsd-h3-lineHeight:2.25rem;--lsd-h4-fontSize:1.5rem;--lsd-h4-fontWeight:normal;--lsd-h4-lineHeight:2rem;--lsd-h5-fontSize:1.25rem;--lsd-h5-fontWeight:normal;--lsd-h5-lineHeight:1.75rem;--lsd-h6-fontSize:1rem;--lsd-h6-fontWeight:normal;--lsd-h6-lineHeight:1.5rem;--lsd-subtitle1-fontSize:1.125rem;--lsd-subtitle1-fontWeight:normal;--lsd-subtitle1-lineHeight:1.5rem;--lsd-subtitle2-fontSize:1rem;--lsd-subtitle2-fontWeight:normal;--lsd-subtitle2-lineHeight:1.5rem;--lsd-subtitle3-fontSize:0.875rem;--lsd-subtitle3-fontWeight:normal;--lsd-subtitle3-lineHeight:1.25rem;--lsd-subtitle4-fontSize:0.75rem;--lsd-subtitle4-fontWeight:normal;--lsd-subtitle4-lineHeight:1rem;--lsd-body1-fontSize:1rem;--lsd-body1-fontWeight:normal;--lsd-body1-lineHeight:1.5rem;--lsd-body2-fontSize:0.875rem;--lsd-body2-fontWeight:normal;--lsd-body2-lineHeight:1.25rem;--lsd-body3-fontSize:0.75rem;--lsd-body3-fontWeight:normal;--lsd-body3-lineHeight:1rem;--lsd-label1-fontSize:0.875rem;--lsd-label1-fontWeight:normal;--lsd-label1-lineHeight:1.25rem;--lsd-label2-fontSize:0.75rem;--lsd-label2-fontWeight:normal;--lsd-label2-lineHeight:1rem;--lsd-typography-generic-font-family:sans-serif;--lsd-theme-primary:255,255,255;--lsd-theme-secondary:0,0,0;--lsd-surface-primary:0,0,0;--lsd-surface-secondary:255,255,255;--lsd-border-primary:255,255,255;--lsd-border-secondary:0,0,0;--lsd-icon-primary:255,255,255;--lsd-icon-secondary:0,0,0;--lsd-text-primary:255,255,255;--lsd-text-secondary:0,0,0;--lsd-text-tertiary:255,255,255,0.34;--lsd-spacing-4:4px;--lsd-spacing-8:8px;--lsd-spacing-16:16px;--lsd-spacing-24:24px;--lsd-spacing-32:32px;--lsd-spacing-40:40px;--lsd-spacing-64:64px;--lsd-spacing-80:80px;--lsd-spacing-96:96px;--lsd-spacing-120:120px;}</style><div class="root_QACb"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="navbar navbar--fixed-top navbarHideable_OoEf"><div class="navbar__inner"><div class="navbar__left"><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--light_BL8e" height="26"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--dark_OvIx" height="26"></div><b class="navbar__title text--truncate"></b></a></div><div class="navbar__left-items"></div><div class="navbar__right-items"><div class="iconButtonGroup_ktNv lsd-icon-button-group lsd-icon-button-group--medium lsd-icon-button-group--outlined"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="main-wrapper mainWrapper_z2l0 docsWrapper_BCFX"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docPage__5DB"><aside class="theme-doc-sidebar-container docSidebarContainer_b6E3"><div class="sidebarViewport_Xe31"><div class="sidebar_UEyd sidebarWithHideableNavbar__00c"><a tabindex="-1" class="sidebarLogo_Ydl9" href="/"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--light_BL8e" height="26"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--dark_OvIx" height="26"><b></b></a><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_NjKY"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/codex/">Codex RFCs</a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="menu__link menu__link--sublist menu__link--active" aria-expanded="true" href="/codex/raw/codex-block-exchange"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="chevron_How5 lsd-icon lsd-icon--small lsd-icon--filled"><path d="M3.5 8.33875L4.3225 9.16125L7 6.48959L9.6775 9.16125L10.5 8.33875L7 4.83875L3.5 8.33875Z" fill="black"></path></svg><span class="lsd-typography lsd-typography--body2 lsd-typography--primary">raw</span></a></div><ul style="display:block;overflow:visible;height:auto" class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/codex/raw/codex-block-exchange">CODEX-BLOCK-EXCHANGE</a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/codex/raw/codex-marketplace">CODEX-MARKETPLACE</a></li></ul></li></ul></nav></div></div></aside><main class="docMainContainer_gTbr"><div class="container padding-top--md padding-bottom--lg"><div class="row docItemGrid_SzoZ"><div class="docItemCol_F52z"><div class="docItemContainer_hrrU"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_RLvU" aria-label="Breadcrumbs"><ul class="breadcrumbs" itemscope="" itemtype="https://schema.org/BreadcrumbList"><a class="breadcrumbs__item" href="/codex"><span class="lsd-typography lsd-typography--body3">Home</span></a><li class="breadcrumbs__item"><span class="lsd-typography lsd-typography--body3 breadcrumbs__link">raw</span><meta itemprop="position" content="1"></li><li itemscope="" itemprop="itemListElement" itemtype="https://schema.org/ListItem" class="breadcrumbs__item breadcrumbs__item--active"><span class="lsd-typography lsd-typography--body3 breadcrumbs__link" itemprop="name">CODEX-BLOCK-EXCHANGE</span><meta itemprop="position" content="2"></li></ul></nav><div class="theme-doc-markdown markdown"><header><h1>CODEX-BLOCK-EXCHANGE</h1><div class="tocMobile_imaF"><div class="tocCollapsible_ROek theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_dxRj"><div></div><span class="lsd-typography lsd-typography--body2">On this page</span><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" class="lsd-icon lsd-icon--small lsd-icon--filled"><path d="M10.5 5.66125L9.6775 4.83875L7 7.51041L4.3225 4.83874L3.5 5.66125L7 9.16125L10.5 5.66125Z" fill="black"></path></svg></button></div></div></header><ul><li>Status: raw</li><li>Category: Standards Track</li><li>Editor: Codex Team</li><li>Contributors:<ul><li>Filip Dimitrijevic <<a href="mailto:filip@status.im" target="_blank" rel="noopener noreferrer">filip@status.im</a>></li></ul></li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="specification-status">Specification Status<a href="#specification-status" class="hash-link" aria-label="Direct link to Specification Status" title="Direct link to Specification Status"></a></h2><p>This specification contains a mix of:</p><ul><li><strong>Verified protocol elements</strong>: Core message formats, protobuf structures, and addressing modes confirmed from implementation</li><li><strong>Design specifications</strong>: Payment flows, state machines, and negotiation strategies representing intended behavior</li><li><strong>Recommended values</strong>: Protocol limits and timeouts that serve as guidelines (actual implementations may vary)</li><li><strong>Pending verification</strong>: Some technical details (e.g., multicodec 0xCD02) require further validation</li></ul><p>Sections marked with notes indicate areas where implementation details may differ from this specification.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="abstract">Abstract<a href="#abstract" class="hash-link" aria-label="Direct link to Abstract" title="Direct link to Abstract"></a></h2><p>The Block Exchange (BE) is a core Codex component responsible for
|
||
peer-to-peer content distribution across the network.
|
||
It manages the sending and receiving of data blocks between nodes,
|
||
enabling efficient data sharing and retrieval.
|
||
This specification defines both an internal service interface and a
|
||
network protocol for referring to and providing data blocks.
|
||
Blocks are uniquely identifiable by means of an address and represent
|
||
fixed-length chunks of arbitrary data.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="semantics">Semantics<a href="#semantics" class="hash-link" aria-label="Direct link to Semantics" title="Direct link to Semantics"></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" target="_blank" rel="noopener noreferrer">RFC 2119</a>.</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="definitions">Definitions<a href="#definitions" class="hash-link" aria-label="Direct link to Definitions" title="Direct link to Definitions"></a></h3><table><thead><tr><th>Term</th><th>Description</th></tr></thead><tbody><tr><td><strong>Block</strong></td><td>Fixed-length chunk of arbitrary data, uniquely identifiable</td></tr><tr><td><strong>Standalone Block</strong></td><td>Self-contained block addressed by SHA256 hash (CID)</td></tr><tr><td><strong>Dataset Block</strong></td><td>Block in ordered set, addressed by dataset CID + index</td></tr><tr><td><strong>Block Address</strong></td><td>Unique identifier for standalone/dataset addressing</td></tr><tr><td><strong>WantList</strong></td><td>List of block requests sent by a peer</td></tr><tr><td><strong>Block Delivery</strong></td><td>Transmission of block data from one peer to another</td></tr><tr><td><strong>Block Presence</strong></td><td>Indicator of whether peer has requested block</td></tr><tr><td><strong>Merkle Proof</strong></td><td>Proof verifying dataset block position correctness</td></tr><tr><td><strong>CodexProof</strong></td><td>Codex-specific Merkle proof format verifying a block's position within a dataset tree</td></tr><tr><td><strong>Stream</strong></td><td>Bidirectional libp2p communication channel between two peers for exchanging messages</td></tr><tr><td><strong>Peer Context Store</strong></td><td>Internal data structure tracking active peer connections, their WantLists, and exchange state</td></tr><tr><td><strong>CID</strong></td><td>Content Identifier - hash-based identifier for content</td></tr><tr><td><strong>Multicodec</strong></td><td>Self-describing format identifier for data encoding</td></tr><tr><td><strong>Multihash</strong></td><td>Self-describing hash format</td></tr></tbody></table><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="motivation">Motivation<a href="#motivation" class="hash-link" aria-label="Direct link to Motivation" title="Direct link to Motivation"></a></h2><p>The Block Exchange module serves as the fundamental layer for content
|
||
distribution in the Codex network.
|
||
It provides primitives for requesting and delivering blocks of data
|
||
between peers, supporting both standalone blocks and blocks that are
|
||
part of larger datasets.
|
||
The protocol is designed to work over libp2p streams and integrates
|
||
with Codex's discovery, storage, and payment systems.</p><p>When a peer wishes to obtain a block, it registers its unique address
|
||
with the Block Exchange, and the Block Exchange will then be in charge
|
||
of procuring it by finding a peer that has the block, if any, and then
|
||
downloading it.
|
||
The Block Exchange will also accept requests from peers which might
|
||
want blocks that the node has, and provide them.</p><p><strong>Discovery Separation:</strong> Throughout this specification we assume that
|
||
if a peer wants a block, then the peer has the means to locate and
|
||
connect to peers which either: (1) have the block; or (2) are
|
||
reasonably expected to obtain the block in the future.
|
||
In practical implementations, the Block Exchange will typically require
|
||
the support of an underlying discovery service, e.g., the Codex DHT,
|
||
to look up such peers, but this is beyond the scope of this document.</p><p>The protocol supports two distinct block types to accommodate different
|
||
use cases: standalone blocks for independent data chunks and dataset
|
||
blocks for ordered collections of data that form larger structures.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="block-format">Block Format<a href="#block-format" class="hash-link" aria-label="Direct link to Block Format" title="Direct link to Block Format"></a></h2><p>The Block Exchange protocol supports two types of blocks:</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="standalone-blocks">Standalone Blocks<a href="#standalone-blocks" class="hash-link" aria-label="Direct link to Standalone Blocks" title="Direct link to Standalone Blocks"></a></h3><p>Standalone blocks are self-contained pieces of data addressed by their
|
||
SHA256 content identifier (CID).
|
||
These blocks are independent and do not reference any larger structure.</p><p><strong>Properties:</strong></p><ul><li>Addressed by content hash (SHA256)</li><li>Default size: 64 KiB</li><li>Self-contained and independently verifiable</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="dataset-blocks">Dataset Blocks<a href="#dataset-blocks" class="hash-link" aria-label="Direct link to Dataset Blocks" title="Direct link to Dataset Blocks"></a></h3><p>Dataset blocks are part of ordered sets and are addressed by a
|
||
<code>(datasetCID, index)</code> tuple.
|
||
The datasetCID refers to the Merkle tree root of the entire dataset,
|
||
and the index indicates the block's position within that dataset.</p><p>Formally, we can define a block as a tuple consisting of raw data and
|
||
its content identifier: <code>(data: seq[byte], cid: Cid)</code>, where standalone
|
||
blocks are addressed by <code>cid</code>, and dataset blocks can be addressed
|
||
either by <code>cid</code> or a <code>(datasetCID, index)</code> tuple.</p><p><strong>Properties:</strong></p><ul><li>Addressed by <code>(treeCID, index)</code> tuple</li><li>Part of a Merkle tree structure</li><li>Require Merkle proof for verification</li><li>Must be uniformly sized within a dataset</li><li>Final blocks MUST be zero-padded if incomplete</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="block-specifications">Block Specifications<a href="#block-specifications" class="hash-link" aria-label="Direct link to Block Specifications" title="Direct link to Block Specifications"></a></h3><p>All blocks in the Codex Block Exchange protocol adhere to the
|
||
following specifications:</p><table><thead><tr><th>Property</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>Default Block Size</td><td>64 KiB</td><td>Standard size for data blocks</td></tr><tr><td>Maximum Block Size</td><td>100 MiB</td><td>Upper limit for block data field</td></tr><tr><td>Multicodec</td><td><code>codex-block</code> (0xCD02)*</td><td>Format identifier</td></tr><tr><td>Multihash</td><td><code>sha2-256</code> (0x12)</td><td>Hash algorithm for addressing</td></tr><tr><td>Padding Requirement</td><td>Zero-padding</td><td>Incomplete final blocks padded</td></tr></tbody></table><p><strong>Note:</strong> *The multicodec value 0xCD02 is not currently registered in the official <a href="https://github.com/multiformats/multicodec/blob/master/table.csv" target="_blank" rel="noopener noreferrer">multiformats multicodec table</a>. This may be a reserved/private code pending official registration.</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="protocol-limits">Protocol Limits<a href="#protocol-limits" class="hash-link" aria-label="Direct link to Protocol Limits" title="Direct link to Protocol Limits"></a></h3><p>To ensure network stability and prevent resource exhaustion, implementations
|
||
SHOULD enforce reasonable limits. The following are <strong>recommended values</strong>
|
||
(actual implementation limits may vary):</p><table><thead><tr><th>Limit</th><th>Recommended Value</th><th>Description</th></tr></thead><tbody><tr><td><strong>Maximum Block Size</strong></td><td>100 MiB</td><td>Maximum size of block data in BlockDelivery</td></tr><tr><td><strong>Maximum WantList Size</strong></td><td>1000 entries</td><td>Maximum entries per WantList message</td></tr><tr><td><strong>Maximum Concurrent Requests</strong></td><td>256 per peer</td><td>Maximum simultaneous block requests per peer</td></tr><tr><td><strong>Stream Timeout</strong></td><td>60 seconds</td><td>Idle stream closure timeout</td></tr><tr><td><strong>Request Timeout</strong></td><td>300 seconds</td><td>Maximum time to fulfill a block request</td></tr><tr><td><strong>Maximum Message Size</strong></td><td>105 MiB</td><td>Maximum total message size (protobuf)</td></tr><tr><td><strong>Maximum Pending Bytes</strong></td><td>10 GiB</td><td>Maximum pending data per peer connection</td></tr></tbody></table><p><strong>Note:</strong> These values are <strong>not verified from implementation</strong> and serve as
|
||
reasonable guidelines. Actual implementations MAY use different limits based
|
||
on their resource constraints and deployment requirements.</p><p><strong>Enforcement:</strong></p><ul><li>Implementations MUST reject messages exceeding their configured size limits</li><li>Implementations SHOULD track per-peer request counts</li><li>Implementations SHOULD close streams exceeding configured timeout limits</li><li>Implementations MAY implement stricter or more lenient limits based on local resources</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="service-interface">Service Interface<a href="#service-interface" class="hash-link" aria-label="Direct link to Service Interface" title="Direct link to Service Interface"></a></h2><p>The Block Exchange module exposes two core primitives for
|
||
block management:</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="requestblock"><code>requestBlock</code><a href="#requestblock" class="hash-link" aria-label="Direct link to requestblock" title="Direct link to requestblock"></a></h3><div class="language-python codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-python codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">requestBlock</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> BlockAddress</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">></span><span class="token plain"> Block</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p>Registers a block address for retrieval and returns the block data
|
||
when available.
|
||
This function can be awaited by the caller until the block is retrieved
|
||
from the network or local storage.</p><p><strong>Parameters:</strong></p><ul><li><code>address</code>: BlockAddress - The unique address identifying the block
|
||
to retrieve</li></ul><p><strong>Returns:</strong></p><ul><li><code>Block</code> - The retrieved block data</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="cancelrequest"><code>cancelRequest</code><a href="#cancelrequest" class="hash-link" aria-label="Direct link to cancelrequest" title="Direct link to cancelrequest"></a></h3><div class="language-python codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-python codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">async</span><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">cancelRequest</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">address</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> BlockAddress</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">></span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">bool</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p>Cancels a previously registered block request.</p><p><strong>Parameters:</strong></p><ul><li><code>address</code>: BlockAddress - The address of the block request to cancel</li></ul><p><strong>Returns:</strong></p><ul><li><code>bool</code> - True if the cancellation was successful, False otherwise</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="dependencies">Dependencies<a href="#dependencies" class="hash-link" aria-label="Direct link to Dependencies" title="Direct link to Dependencies"></a></h2><p>The Block Exchange module depends on and interacts with several other
|
||
Codex components:</p><table><thead><tr><th>Component</th><th>Purpose</th></tr></thead><tbody><tr><td><strong>Discovery Module</strong></td><td>DHT-based peer discovery for locating nodes</td></tr><tr><td><strong>Local Store (Repo)</strong></td><td>Persistent block storage for local blocks</td></tr><tr><td><strong>Advertiser</strong></td><td>Announces block availability to the network</td></tr><tr><td><strong>Network Layer</strong></td><td>libp2p connections and stream management</td></tr></tbody></table><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="protocol-specification">Protocol Specification<a href="#protocol-specification" class="hash-link" aria-label="Direct link to Protocol Specification" title="Direct link to Protocol Specification"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="protocol-identifier">Protocol Identifier<a href="#protocol-identifier" class="hash-link" aria-label="Direct link to Protocol Identifier" title="Direct link to Protocol Identifier"></a></h3><p>The Block Exchange protocol uses the following libp2p protocol
|
||
identifier:</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">/codex/blockexc/1.0.0</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="version-negotiation">Version Negotiation<a href="#version-negotiation" class="hash-link" aria-label="Direct link to Version Negotiation" title="Direct link to Version Negotiation"></a></h3><p>The protocol version is negotiated through libp2p's multistream-select
|
||
protocol during connection establishment. The following describes standard
|
||
libp2p version negotiation behavior; actual Codex implementation details
|
||
may vary.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="protocol-versioning">Protocol Versioning<a href="#protocol-versioning" class="hash-link" aria-label="Direct link to Protocol Versioning" title="Direct link to Protocol Versioning"></a></h4><p><strong>Version Format</strong>: <code>/codex/blockexc/<major>.<minor>.<patch></code></p><ul><li><strong>Major version</strong>: Incompatible protocol changes</li><li><strong>Minor version</strong>: Backward-compatible feature additions</li><li><strong>Patch version</strong>: Backward-compatible bug fixes</li></ul><p><strong>Current Version</strong>: <code>1.0.0</code></p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="version-negotiation-process">Version Negotiation Process<a href="#version-negotiation-process" class="hash-link" aria-label="Direct link to Version Negotiation Process" title="Direct link to Version Negotiation Process"></a></h4><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">1. Initiator opens stream</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">2. Initiator proposes: "/codex/blockexc/1.0.0"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">3. Responder checks supported versions</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">4. If supported:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Responder accepts: "/codex/blockexc/1.0.0"</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Connection established</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">5. If not supported:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Responder rejects with: "na" (not available)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Try fallback version or close connection</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="compatibility-rules">Compatibility Rules<a href="#compatibility-rules" class="hash-link" aria-label="Direct link to Compatibility Rules" title="Direct link to Compatibility Rules"></a></h4><p><strong>Major Version Compatibility:</strong></p><ul><li>Major version <code>1.x.x</code> is incompatible with <code>2.x.x</code></li><li>Nodes MUST support only their major version</li><li>Cross-major-version communication requires protocol upgrade</li></ul><p><strong>Minor Version Compatibility:</strong></p><ul><li>Version <code>1.1.0</code> MUST be backward compatible with <code>1.0.0</code></li><li>Newer minors MAY include optional features</li><li>Older nodes ignore unknown message fields (protobuf semantics)</li></ul><p><strong>Patch Version Compatibility:</strong></p><ul><li>All patches within same minor version are fully compatible</li><li>Patches fix bugs without changing protocol behavior</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="multi-version-support">Multi-Version Support<a href="#multi-version-support" class="hash-link" aria-label="Direct link to Multi-Version Support" title="Direct link to Multi-Version Support"></a></h4><p>Implementations MAY support multiple protocol versions simultaneously:</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Supported protocols (in preference order):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 1. /codex/blockexc/1.2.0 (preferred, latest features)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 2. /codex/blockexc/1.1.0 (fallback, stable)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 3. /codex/blockexc/1.0.0 (legacy support)</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Negotiation Strategy:</strong></p><ol><li>Propose highest supported version first</li><li>If rejected, try next lower version</li><li>If all rejected, connection fails</li><li>Track peer's supported version for future connections</li></ol><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="feature-detection">Feature Detection<a href="#feature-detection" class="hash-link" aria-label="Direct link to Feature Detection" title="Direct link to Feature Detection"></a></h4><p>For optional features within same major.minor version:</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Method 1: Message field presence</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> - Send message with optional field</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> - Peer ignores if not supported (protobuf default)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Method 2: Capability exchange (future extension)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> - Exchange capability bitmask in initial message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> - Enable features only if both peers support</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="version-upgrade-path">Version Upgrade Path<a href="#version-upgrade-path" class="hash-link" aria-label="Direct link to Version Upgrade Path" title="Direct link to Version Upgrade Path"></a></h4><p><strong>Backward Compatibility:</strong></p><ul><li>New versions MUST handle messages from older versions</li><li>Unknown message fields silently ignored</li><li>Unknown WantList flags ignored</li><li>Unknown BlockPresence types treated as DontHave</li></ul><p><strong>Forward Compatibility:</strong></p><ul><li>Older versions MAY ignore new message types</li><li>Critical features require major version bump</li><li>Optional features use minor version bump</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="connection-model">Connection Model<a href="#connection-model" class="hash-link" aria-label="Direct link to Connection Model" title="Direct link to Connection Model"></a></h3><p>The protocol operates over libp2p streams.
|
||
When a node wants to communicate with a peer:</p><ol><li>The initiating node dials the peer using the protocol identifier</li><li>A bidirectional stream is established</li><li>Both sides can send and receive messages on this stream</li><li>Messages are encoded using Protocol Buffers</li><li>The stream remains open for the duration of the exchange session</li><li>Peers track active connections in a peer context store</li></ol><p>The protocol handles peer lifecycle events:</p><ul><li><strong>Peer Joined</strong>: When a peer connects, it is added to the active
|
||
peer set</li><li><strong>Peer Departed</strong>: When a peer disconnects gracefully, its context
|
||
is cleaned up</li><li><strong>Peer Dropped</strong>: When a peer connection fails, it is removed from
|
||
the active set</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="message-flow-examples">Message Flow Examples<a href="#message-flow-examples" class="hash-link" aria-label="Direct link to Message Flow Examples" title="Direct link to Message Flow Examples"></a></h3><p>This section illustrates typical message exchange sequences for common
|
||
block exchange scenarios.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-1-standalone-block-request">Example 1: Standalone Block Request<a href="#example-1-standalone-block-request" class="hash-link" aria-label="Direct link to Example 1: Standalone Block Request" title="Direct link to Example 1: Standalone Block Request"></a></h4><p><strong>Scenario</strong>: Node A requests a standalone block from Node B</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Node A Node B</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |--- Message(wantlist) ------------------>|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmABC123 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantType = wantBlock |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | priority = 0 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |<-- Message(blockPresences, payload) ----|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | blockPresences[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmABC123 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | type = presenceHave |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | payload[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | cid = QmABC123 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | data = <64 KiB block data> |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmABC123 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Steps:</strong></p><ol><li>Node A sends WantList requesting block with <code>wantType = wantBlock</code></li><li>Node B checks local storage, finds block</li><li>Node B responds with BlockPresence confirming availability</li><li>Node B includes BlockDelivery with actual block data</li><li>Node A verifies CID matches SHA256(data)</li><li>Node A stores block locally</li></ol><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-2-dataset-block-request-with-merkle-proof">Example 2: Dataset Block Request with Merkle Proof<a href="#example-2-dataset-block-request-with-merkle-proof" class="hash-link" aria-label="Direct link to Example 2: Dataset Block Request with Merkle Proof" title="Direct link to Example 2: Dataset Block Request with Merkle Proof"></a></h4><p><strong>Scenario</strong>: Node A requests a dataset block from Node B</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Node A Node B</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |--- Message(wantlist) ------------------>|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.leaf = true |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.treeCid = QmTree456 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.index = 42 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantType = wantBlock |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |<-- Message(payload) ---------------------|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | payload[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | cid = QmBlock789 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | data = <64 KiB zero-padded data> |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.leaf = true |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.treeCid = QmTree456 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.index = 42 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | proof = <CodexProof bytes> |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Steps:</strong></p><ol><li>Node A sends WantList for dataset block at specific index</li><li>Node B locates block in dataset</li><li>Node B generates CodexProof for block position in Merkle tree</li><li>Node B delivers block with proof</li><li>Node A verifies proof against treeCid</li><li>Node A verifies block data integrity</li><li>Node A stores block with dataset association</li></ol><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-3-block-presence-check-wanthave">Example 3: Block Presence Check (wantHave)<a href="#example-3-block-presence-check-wanthave" class="hash-link" aria-label="Direct link to Example 3: Block Presence Check (wantHave)" title="Direct link to Example 3: Block Presence Check (wantHave)"></a></h4><p><strong>Scenario</strong>: Node A checks if Node B has a block without requesting full data</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Node A Node B</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |--- Message(wantlist) ------------------>|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmCheck999 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantType = wantHave |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | sendDontHave = true |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |<-- Message(blockPresences) -------------|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | blockPresences[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmCheck999 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | type = presenceHave |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | price = 0x00 (free) |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Steps:</strong></p><ol><li>Node A sends WantList with <code>wantType = wantHave</code></li><li>Node B checks local storage without loading block data</li><li>Node B responds with BlockPresence only (no payload)</li><li>Node A updates peer availability map</li><li>If Node A decides to request, sends new WantList with <code>wantType = wantBlock</code></li></ol><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-4-block-not-available">Example 4: Block Not Available<a href="#example-4-block-not-available" class="hash-link" aria-label="Direct link to Example 4: Block Not Available" title="Direct link to Example 4: Block Not Available"></a></h4><p><strong>Scenario</strong>: Node A requests block Node B doesn't have</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Node A Node B</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |--- Message(wantlist) ------------------>|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmMissing111 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantType = wantBlock |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | sendDontHave = true |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |<-- Message(blockPresences) -------------|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | blockPresences[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmMissing111 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | type = presenceDontHave |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Steps:</strong></p><ol><li>Node A requests block with <code>sendDontHave = true</code></li><li>Node B checks storage, block not found</li><li>Node B sends BlockPresence with <code>presenceDontHave</code></li><li>Node A removes Node B from candidates for this block</li><li>Node A queries discovery service for alternative peers</li></ol><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-5-wantlist-cancellation">Example 5: WantList Cancellation<a href="#example-5-wantlist-cancellation" class="hash-link" aria-label="Direct link to Example 5: WantList Cancellation" title="Direct link to Example 5: WantList Cancellation"></a></h4><p><strong>Scenario</strong>: Node A cancels a previous block request</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Node A Node B</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |--- Message(wantlist) ------------------>|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmCancel222 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | cancel = true |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Steps:</strong></p><ol><li>Node A sends WantList entry with <code>cancel = true</code></li><li>Node B removes block request from peer's want queue</li><li>Node B stops any pending block transfer for this address</li><li>No response message required for cancellation</li></ol><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-6-delta-wantlist-update">Example 6: Delta WantList Update<a href="#example-6-delta-wantlist-update" class="hash-link" aria-label="Direct link to Example 6: Delta WantList Update" title="Direct link to Example 6: Delta WantList Update"></a></h4><p><strong>Scenario</strong>: Node A adds requests to existing WantList</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Node A Node B</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> |--- Message(wantlist) ------------------>|</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.full = false |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[0]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmNew1 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantType = wantBlock |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantlist.entries[1]: |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | address.cid = QmNew2 |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | wantType = wantBlock |</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> | |</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Steps:</strong></p><ol><li>Node A sends WantList with <code>full = false</code> (delta update)</li><li>Node B merges entries with existing WantList for Node A</li><li>Node B begins processing new requests</li><li>Previous WantList entries remain active</li></ol><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="sequence-diagrams">Sequence Diagrams<a href="#sequence-diagrams" class="hash-link" aria-label="Direct link to Sequence Diagrams" title="Direct link to Sequence Diagrams"></a></h3><p>These diagrams illustrate the complete flow of block exchange operations
|
||
including service interface, peer discovery, and network protocol interactions.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="complete-block-request-flow">Complete Block Request Flow<a href="#complete-block-request-flow" class="hash-link" aria-label="Direct link to Complete Block Request Flow" title="Direct link to Complete Block Request Flow"></a></h4><p>The protocol supports two strategies for WantBlock requests,
|
||
each with different trade-offs.
|
||
Implementations may choose the strategy based on network conditions,
|
||
peer availability, and resource constraints.</p><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="strategy-1-parallel-request-low-latency">Strategy 1: Parallel Request (Low Latency)<a href="#strategy-1-parallel-request-low-latency" class="hash-link" aria-label="Direct link to Strategy 1: Parallel Request (Low Latency)" title="Direct link to Strategy 1: Parallel Request (Low Latency)"></a></h5><p>In this strategy, the requester sends <code>wantType = wantBlock</code> to all
|
||
discovered peers simultaneously.
|
||
This minimizes latency as the first peer to respond with the block
|
||
data wins, but it wastes bandwidth since multiple peers may send
|
||
the same block data.</p><p><strong>Trade-offs:</strong></p><ul><li><strong>Pro</strong>: Lowest latency - block arrives as soon as any peer can deliver it</li><li><strong>Pro</strong>: More resilient to slow or unresponsive peers</li><li><strong>Con</strong>: Bandwidth-wasteful - multiple peers may send duplicate data</li><li><strong>Con</strong>: Higher network overhead for the requester</li><li><strong>Best for</strong>: Time-critical data retrieval, unreliable networks</li></ul><div class="wrapper_SWrM active_qZD5"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="strategy-2-two-phase-discovery-bandwidth-efficient">Strategy 2: Two-Phase Discovery (Bandwidth Efficient)<a href="#strategy-2-two-phase-discovery-bandwidth-efficient" class="hash-link" aria-label="Direct link to Strategy 2: Two-Phase Discovery (Bandwidth Efficient)" title="Direct link to Strategy 2: Two-Phase Discovery (Bandwidth Efficient)"></a></h5><p>In this strategy, the requester first sends <code>wantType = wantHave</code> to
|
||
discover which peers have the block, then sends <code>wantType = wantBlock</code>
|
||
only to a single selected peer.
|
||
This conserves bandwidth but adds an extra round-trip of latency.</p><p><strong>Trade-offs:</strong></p><ul><li><strong>Pro</strong>: Bandwidth-efficient - only one peer sends block data</li><li><strong>Pro</strong>: Enables price comparison before committing to a peer</li><li><strong>Pro</strong>: Allows selection based on peer reputation or proximity</li><li><strong>Con</strong>: Higher latency due to extra round-trip for presence check</li><li><strong>Con</strong>: Selected peer may become unavailable between phases</li><li><strong>Best for</strong>: Large blocks, paid content, bandwidth-constrained networks</li></ul><div class="wrapper_SWrM active_qZD5"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="hybrid-approach">Hybrid Approach<a href="#hybrid-approach" class="hash-link" aria-label="Direct link to Hybrid Approach" title="Direct link to Hybrid Approach"></a></h5><p>Implementations MAY combine both strategies:</p><ol><li>Use two-phase discovery for large blocks or paid content</li><li>Use parallel requests for small blocks or time-critical data</li><li>Adaptively switch strategies based on network conditions</li></ol><div class="wrapper_SWrM active_qZD5"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="dataset-block-verification-flow">Dataset Block Verification Flow<a href="#dataset-block-verification-flow" class="hash-link" aria-label="Direct link to Dataset Block Verification Flow" title="Direct link to Dataset Block Verification Flow"></a></h4><div class="wrapper_SWrM active_qZD5"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="payment-flow-with-state-channels">Payment Flow with State Channels<a href="#payment-flow-with-state-channels" class="hash-link" aria-label="Direct link to Payment Flow with State Channels" title="Direct link to Payment Flow with State Channels"></a></h4><div class="wrapper_SWrM active_qZD5"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="peer-lifecycle-management">Peer Lifecycle Management<a href="#peer-lifecycle-management" class="hash-link" aria-label="Direct link to Peer Lifecycle Management" title="Direct link to Peer Lifecycle Management"></a></h4><div class="wrapper_SWrM active_qZD5"><button class="fullscreenButton_Bocn lsd-icon-button lsd-icon-button--medium lsd-icon-button--outlined"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M1.75 2.917V5.25h1.167V2.917H5.25V1.75H2.917A1.17 1.17 0 0 0 1.75 2.917ZM2.917 8.75H1.75v2.333a1.17 1.17 0 0 0 1.167 1.167H5.25v-1.167H2.917V8.75Zm8.166 2.333H8.75v1.167h2.333a1.17 1.17 0 0 0 1.167-1.167V8.75h-1.167v2.333Zm0-9.333H8.75v1.167h2.333V5.25h1.167V2.917a1.17 1.17 0 0 0-1.167-1.167Z" fill="#fff"></path></svg></div></button></div><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="message-format">Message Format<a href="#message-format" class="hash-link" aria-label="Direct link to Message Format" title="Direct link to Message Format"></a></h3><p>All messages use Protocol Buffers encoding for serialization.
|
||
The main message structure supports multiple operation types in a
|
||
single message.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="main-message-structure">Main Message Structure<a href="#main-message-structure" class="hash-link" aria-label="Direct link to Main Message Structure" title="Direct link to Main Message Structure"></a></h4><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Wantlist wantlist = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Field 2 reserved for future use</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated BlockDelivery payload = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated BlockPresence blockPresences = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> int32 pendingBytes = 5;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> AccountMessage account = 6;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> StateChannelUpdate payment = 7;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Fields:</strong></p><ul><li><code>wantlist</code>: Block requests from the sender</li><li>Field 2: Reserved (unused, see note below)</li><li><code>payload</code>: Block deliveries (actual block data)</li><li><code>blockPresences</code>: Availability indicators for requested blocks</li><li><code>pendingBytes</code>: Number of bytes pending delivery</li><li><code>account</code>: Account information for micropayments</li><li><code>payment</code>: State channel update for payment processing</li></ul><p><strong>Note on Missing Field 2:</strong></p><p>Field number 2 is intentionally skipped in the Message protobuf definition.
|
||
This is a common protobuf practice for several reasons:</p><ul><li><strong>Protocol Evolution</strong>: Field 2 may have been used in earlier versions and
|
||
removed, with the field number reserved to prevent reuse</li><li><strong>Forward Compatibility</strong>: Reserving field numbers ensures old clients can
|
||
safely ignore new fields</li><li><strong>Implementation History</strong>: May have been used during development and removed
|
||
before final release</li></ul><p>The gap does not affect protocol operation. Protobuf field numbers need not be
|
||
sequential, and skipping numbers is standard practice for protocol evolution.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="block-address">Block Address<a href="#block-address" class="hash-link" aria-label="Direct link to Block Address" title="Direct link to Block Address"></a></h4><p>The BlockAddress structure supports both standalone and dataset
|
||
block addressing:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool leaf = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes treeCid = 2; // Present when leaf = true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> uint64 index = 3; // Present when leaf = true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes cid = 4; // Present when leaf = false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Fields:</strong></p><ul><li><code>leaf</code>: Indicates if this is dataset block (true) or standalone
|
||
(false)</li><li><code>treeCid</code>: Merkle tree root CID (present when <code>leaf = true</code>)</li><li><code>index</code>: Position of block within dataset (present when <code>leaf = true</code>)</li><li><code>cid</code>: Content identifier of the block (present when <code>leaf = false</code>)</li></ul><p><strong>Addressing Modes:</strong></p><ul><li><strong>Standalone Block</strong> (<code>leaf = false</code>): Direct CID reference to a
|
||
standalone content block</li><li><strong>Dataset Block</strong> (<code>leaf = true</code>): Reference to a block within an
|
||
ordered set, identified by a Merkle tree root and an index.
|
||
The Merkle root may refer to either a regular dataset, or a dataset
|
||
that has undergone erasure-coding</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="wantlist">WantList<a href="#wantlist" class="hash-link" aria-label="Direct link to WantList" title="Direct link to WantList"></a></h4><p>The WantList communicates which blocks a peer desires to receive:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message Wantlist {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> enum WantType {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantBlock = 0;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantHave = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> message Entry {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockAddress address = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> int32 priority = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool cancel = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> WantType wantType = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool sendDontHave = 5;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> repeated Entry entries = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bool full = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>WantType Values:</strong></p><ul><li><code>wantBlock (0)</code>: Request full block delivery</li><li><code>wantHave (1)</code>: Request availability information only (presence check)</li></ul><p><strong>Entry Fields:</strong></p><ul><li><code>address</code>: The block being requested</li><li><code>priority</code>: Request priority (currently always 0, reserved for future use)</li><li><code>cancel</code>: If true, cancels a previous want for this block</li><li><code>wantType</code>: Specifies whether full block or presence is desired<ul><li><code>wantHave (1)</code>: Only check if peer has the block</li><li><code>wantBlock (0)</code>: Request full block data</li></ul></li><li><code>sendDontHave</code>: If true, peer should respond even if it doesn't have
|
||
the block</li></ul><p><strong>Priority Field Clarification:</strong></p><p>The <code>priority</code> field is currently fixed at <code>0</code> in all implementations and is
|
||
reserved for future protocol extensions. Originally intended for request
|
||
prioritization, this feature is not yet implemented.</p><p><strong>Current Behavior:</strong></p><ul><li>All WantList entries use <code>priority = 0</code></li><li>Implementations MUST accept priority values but MAY ignore them</li><li>Blocks are processed in order received, not by priority</li></ul><p><strong>Future Extensions:</strong></p><p>The priority field is reserved for:</p><ul><li><strong>Bandwidth Management</strong>: Higher priority blocks served first during congestion</li><li><strong>Time-Critical Data</strong>: Urgent blocks (e.g., recent dataset indices) prioritized</li><li><strong>Fair Queueing</strong>: Priority-based scheduling across multiple peers</li><li><strong>QoS Tiers</strong>: Different service levels based on payment/reputation</li></ul><p><strong>Implementation Notes:</strong></p><ul><li>Senders SHOULD set <code>priority = 0</code> for compatibility</li><li>Receivers MUST NOT reject messages with non-zero priority</li><li>Future protocol versions may activate priority-based scheduling</li><li>When activated, higher priority values = higher priority (0 = lowest)</li></ul><p><strong>WantList Fields:</strong></p><ul><li><code>entries</code>: List of block requests</li><li><code>full</code>: If true, replaces all previous entries; if false, delta update</li></ul><p><strong>Delta Updates:</strong></p><p>WantLists support delta updates for efficiency.
|
||
When <code>full = false</code>, entries represent additions or modifications to
|
||
the existing WantList rather than a complete replacement.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="block-delivery">Block Delivery<a href="#block-delivery" class="hash-link" aria-label="Direct link to Block Delivery" title="Direct link to Block Delivery"></a></h4><p>Block deliveries contain the actual block data along with verification
|
||
information:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message BlockDelivery {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes cid = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes data = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockAddress address = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes proof = 4;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Fields:</strong></p><ul><li><code>cid</code>: Content identifier of the block</li><li><code>data</code>: Raw block data (up to 100 MiB)</li><li><code>address</code>: The BlockAddress identifying this block</li><li><code>proof</code>: Merkle proof (CodexProof) verifying block correctness
|
||
(required for dataset blocks)</li></ul><p><strong>Merkle Proof Verification:</strong></p><p>When delivering dataset blocks (<code>address.leaf = true</code>):</p><ul><li>The delivery MUST include a Merkle proof (CodexProof)</li><li>The proof verifies that the block at the given index is correctly
|
||
part of the Merkle tree identified by the tree CID</li><li>This applies to all datasets, irrespective of whether they have been
|
||
erasure-coded or not</li><li>Recipients MUST verify the proof before accepting the block</li><li>Invalid proofs result in block rejection</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="block-presence">Block Presence<a href="#block-presence" class="hash-link" aria-label="Direct link to Block Presence" title="Direct link to Block Presence"></a></h4><p>Block presence messages indicate whether a peer has or does not have a
|
||
requested block:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">enum BlockPresenceType {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> presenceHave = 0;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> presenceDontHave = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">message BlockPresence {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockAddress address = 1;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockPresenceType type = 2;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes price = 3;</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Fields:</strong></p><ul><li><code>address</code>: The block address being referenced</li><li><code>type</code>: Whether the peer has the block or not</li><li><code>price</code>: Price in wei (UInt256 format, see below)</li></ul><p><strong>UInt256 Price Format:</strong></p><p>The <code>price</code> field encodes a 256-bit unsigned integer representing the cost in
|
||
wei (the smallest Ethereum denomination, where 1 ETH = 10^18 wei).</p><p><strong>Encoding Specification:</strong></p><ul><li><strong>Format</strong>: 32 bytes, big-endian byte order</li><li><strong>Type</strong>: Unsigned 256-bit integer</li><li><strong>Range</strong>: 0 to 2^256 - 1</li><li><strong>Zero Price</strong>: <code>0x0000000000000000000000000000000000000000000000000000000000000000</code>
|
||
(block is free)</li></ul><p><strong>Examples:</strong></p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Free (0 wei):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 0x0000000000000000000000000000000000000000000000000000000000000000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">1 wei:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 0x0000000000000000000000000000000000000000000000000000000000000001</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">1 gwei (10^9 wei):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 0x000000000000000000000000000000000000000000000000000000003b9aca00</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">0.001 ETH (10^15 wei):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 0x00000000000000000000000000000000000000000000000000038d7ea4c68000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">1 ETH (10^18 wei):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 0x0000000000000000000000000000000000000000000000000de0b6b3a7640000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Maximum (2^256 - 1):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Conversion Logic:</strong></p><div class="language-python codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-python codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token comment" style="color:rgb(98, 114, 164)"># Wei to bytes (big-endian)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">wei_to_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount_wei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">int</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">></span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> amount_wei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">to_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token number">32</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> byteorder</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">'big'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># Bytes to wei</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">bytes_to_wei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">price_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">></span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">int</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">int</span><span class="token punctuation" style="color:rgb(248, 248, 242)">.</span><span class="token plain">from_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">price_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> byteorder</span><span class="token operator">=</span><span class="token string" style="color:rgb(255, 121, 198)">'big'</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token comment" style="color:rgb(98, 114, 164)"># ETH to wei to bytes</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">def</span><span class="token plain"> </span><span class="token function" style="color:rgb(80, 250, 123)">eth_to_price_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount_eth</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">float</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"> </span><span class="token operator">-</span><span class="token operator">></span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> amount_wei </span><span class="token operator">=</span><span class="token plain"> </span><span class="token builtin" style="color:rgb(189, 147, 249)">int</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount_eth </span><span class="token operator">*</span><span class="token plain"> </span><span class="token number">10</span><span class="token operator">**</span><span class="token number">18</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token keyword" style="color:rgb(189, 147, 249);font-style:italic">return</span><span class="token plain"> wei_to_bytes</span><span class="token punctuation" style="color:rgb(248, 248, 242)">(</span><span class="token plain">amount_wei</span><span class="token punctuation" style="color:rgb(248, 248, 242)">)</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="payment-messages">Payment Messages<a href="#payment-messages" class="hash-link" aria-label="Direct link to Payment Messages" title="Direct link to Payment Messages"></a></h4><p>Payment-related messages for micropayments using Nitro state channels.</p><p><strong>Account Message:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message AccountMessage {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes address = 1; // Ethereum address to which payments should be made</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Fields:</strong></p><ul><li><code>address</code>: Ethereum address for receiving payments</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="concrete-message-examples">Concrete Message Examples<a href="#concrete-message-examples" class="hash-link" aria-label="Direct link to Concrete Message Examples" title="Direct link to Concrete Message Examples"></a></h3><p>This section provides real-world examples of protobuf messages for different
|
||
block exchange scenarios.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-1-simple-standalone-block-request">Example 1: Simple Standalone Block Request<a href="#example-1-simple-standalone-block-request" class="hash-link" aria-label="Direct link to Example 1: Simple Standalone Block Request" title="Direct link to Example 1: Simple Standalone Block Request"></a></h4><p><strong>Scenario</strong>: Request a single standalone block</p><p><strong>Protobuf (wire format representation):</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantlist: Wantlist {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> entries: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Entry {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9 // CID bytes</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> priority: 0</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cancel: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantType: wantBlock // 0</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> sendDontHave: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> full: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Hex representation (sample):</strong></p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">0a2e 0a2c 0a24 0001 5512 2012 20b9 4d27</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">b993 4d3e 08a5 2e52 d7da 7dab fac4 84ef</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">e37a 5380 ee90 88f7 ace2 efcd e910 0018</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">0020 0028 011201 01</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-2-dataset-block-request">Example 2: Dataset Block Request<a href="#example-2-dataset-block-request" class="hash-link" aria-label="Direct link to Example 2: Dataset Block Request" title="Direct link to Example 2: Dataset Block Request"></a></h4><p><strong>Scenario</strong>: Request block at index 100 from dataset</p><p><strong>Protobuf:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantlist: Wantlist {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> entries: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Entry {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> treeCid: 0x0155a0e40220c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 // Tree CID</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> index: 100</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> priority: 0</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cancel: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantType: wantBlock</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> sendDontHave: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> full: false // Delta update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-3-block-delivery-with-proof">Example 3: Block Delivery with Proof<a href="#example-3-block-delivery-with-proof" class="hash-link" aria-label="Direct link to Example 3: Block Delivery with Proof" title="Direct link to Example 3: Block Delivery with Proof"></a></h4><p><strong>Scenario</strong>: Provider sends dataset block with Merkle proof</p><p><strong>Protobuf:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> payload: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockDelivery {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220a1b2c3d4e5f6071829... // Block CID</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> data: <65536 bytes of block data> // 64 KiB</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> treeCid: 0x0155a0e40220c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> index: 100</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> proof: <CodexProof bytes> // Merkle proof data</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Contains: path indices, sibling hashes, tree height</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Format: Implementation-specific (e.g., [height][index][hash1][hash2]...[hashN])</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Size varies by tree depth (illustrative: ~1KB for depth-10 tree)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-4-block-presence-response">Example 4: Block Presence Response<a href="#example-4-block-presence-response" class="hash-link" aria-label="Direct link to Example 4: Block Presence Response" title="Direct link to Example 4: Block Presence Response"></a></h4><p><strong>Scenario</strong>: Provider indicates block availability with price</p><p><strong>Protobuf:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> blockPresences: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockPresence {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> type: presenceHave // 0</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> price: 0x00000000000000000000000000000000000000000000000000038d7ea4c68000 // 0.001 ETH in wei</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-5-payment-message">Example 5: Payment Message<a href="#example-5-payment-message" class="hash-link" aria-label="Direct link to Example 5: Payment Message" title="Direct link to Example 5: Payment Message"></a></h4><p><strong>Scenario</strong>: Send payment via state channel update</p><p><strong>Protobuf:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> account: AccountMessage {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: 0x742d35Cc6634C0532925a3b844200a717C48D6d9 // 20 bytes Ethereum address</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> payment: StateChannelUpdate {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> update: <JSON bytes></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Contains signed Nitro state as UTF-8 JSON string</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> // Example: {"channelId":"0x1234...","nonce":42,...}</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-6-multiple-operations-in-one-message">Example 6: Multiple Operations in One Message<a href="#example-6-multiple-operations-in-one-message" class="hash-link" aria-label="Direct link to Example 6: Multiple Operations in One Message" title="Direct link to Example 6: Multiple Operations in One Message"></a></h4><p><strong>Scenario</strong>: Combined WantList, BlockPresence, and Delivery</p><p><strong>Protobuf:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantlist: Wantlist {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> entries: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Entry {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220... // Requesting new block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantType: wantBlock</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> priority: 0</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cancel: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> sendDontHave: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> full: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> blockPresences: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockPresence {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220... // Response to previous request</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> type: presenceHave</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> price: 0x00 // Free</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> payload: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> BlockDelivery {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220... // Delivering another block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> data: <65536 bytes></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220...</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> pendingBytes: 131072 // 128 KiB more data pending</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="example-7-wantlist-cancellation">Example 7: WantList Cancellation<a href="#example-7-wantlist-cancellation" class="hash-link" aria-label="Direct link to Example 7: WantList Cancellation" title="Direct link to Example 7: WantList Cancellation"></a></h4><p><strong>Scenario</strong>: Cancel multiple pending requests</p><p><strong>Protobuf:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> wantlist: Wantlist {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> entries: [</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Entry {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cid: 0x0155a0e40220abc123...</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cancel: true // Cancellation flag</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> },</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Entry {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: BlockAddress {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> leaf: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> treeCid: 0x0155a0e40220def456...</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> index: 50</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> cancel: true</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> full: false</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="cid-format-details">CID Format Details<a href="#cid-format-details" class="hash-link" aria-label="Direct link to CID Format Details" title="Direct link to CID Format Details"></a></h4><p><strong>CID Structure:</strong></p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">CID v1 format (multibase + multicodec + multihash):</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">[0x01] [0x55] [0xa0] [0xe4] [0x02] [0x20] [<32 bytes SHA256 hash>]</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │ │ │ │ │ │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │ │ │ │ │ └─ Hash digest</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │ │ │ │ └───────── Hash length (32)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │ │ │ └──────────────── Hash algorithm (SHA2-256)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │ │ └─────────────────────── Codec size</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │ └────────────────────────────── Codec (raw = 0x55)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ └───────────────────────────────────── Multicodec prefix</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> └──────────────────────────────────────────── CID version (1)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Actual: 0x01 55 a0 e4 02 20 <hash bytes></span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Example Block CID Breakdown:</strong></p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Full CID: 0x0155a0e40220b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Parts:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Version: 0x01 (CID v1)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Multicodec: 0x55 (raw)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Codec Size: 0xa0e402 (codex-block = 0xCD02, varint encoded)*</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Hash Type: 0x20 (SHA2-256)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Hash Len: 0x12 (20) (32 bytes)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Hash: b94d27b993... (32 bytes SHA256)</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>State Channel Update:</strong></p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">message StateChannelUpdate {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> bytes update = 1; // Signed Nitro state, serialized as JSON</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Fields:</strong></p><ul><li><code>update</code>: Nitro state channel update containing payment information</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="payment-flow-and-price-negotiation">Payment Flow and Price Negotiation<a href="#payment-flow-and-price-negotiation" class="hash-link" aria-label="Direct link to Payment Flow and Price Negotiation" title="Direct link to Payment Flow and Price Negotiation"></a></h3><p>The Block Exchange protocol integrates with Nitro state channels to enable
|
||
micropayments for block delivery.</p><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="payment-requirements">Payment Requirements<a href="#payment-requirements" class="hash-link" aria-label="Direct link to Payment Requirements" title="Direct link to Payment Requirements"></a></h4><p><strong>When Payment is Required:</strong></p><ul><li>Blocks marked as paid content by the provider</li><li>Provider's local policy requires payment for specific blocks</li><li>Block size exceeds free tier threshold (implementation-defined)</li><li>Requester has insufficient credit with provider</li></ul><p><strong>Free Blocks:</strong></p><ul><li>Blocks explicitly marked as free (<code>price = 0x00</code>)</li><li>Blocks exchanged between trusted peers</li><li>Small metadata blocks (implementation-defined)</li></ul><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="price-discovery">Price Discovery<a href="#price-discovery" class="hash-link" aria-label="Direct link to Price Discovery" title="Direct link to Price Discovery"></a></h4><p><strong>Initial Price Advertisement:</strong></p><ol><li>Requester sends WantList with <code>wantType = wantHave</code></li><li>Provider responds with BlockPresence including <code>price</code> field</li><li>Price encoded as UInt256 in wei (smallest Ethereum unit)</li><li>Requester evaluates price against local policy</li></ol><p><strong>Price Format:</strong></p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">price: bytes (32 bytes, big-endian UInt256)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Example: 0x0000000000000000000000000000000000000000000000000de0b6b3a7640000</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> represents 1 ETH = 10^18 wei</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="payment-negotiation-process">Payment Negotiation Process<a href="#payment-negotiation-process" class="hash-link" aria-label="Direct link to Payment Negotiation Process" title="Direct link to Payment Negotiation Process"></a></h4><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="step-1-price-quote">Step 1: Price Quote<a href="#step-1-price-quote" class="hash-link" aria-label="Direct link to Step 1: Price Quote" title="Direct link to Step 1: Price Quote"></a></h5><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Requester → Provider: Message(wantlist: wantHave)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Provider → Requester: BlockPresence(type=presenceHave, price=<amount>)</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="step-2-payment-decision">Step 2: Payment Decision<a href="#step-2-payment-decision" class="hash-link" aria-label="Direct link to Step 2: Payment Decision" title="Direct link to Step 2: Payment Decision"></a></h5><p>Requester evaluates price:</p><ul><li><strong>Accept</strong>: Proceed to payment</li><li><strong>Reject</strong>: Send cancellation</li><li><strong>Counter</strong>: Not supported in current protocol (future extension)</li></ul><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="step-3-state-channel-update">Step 3: State Channel Update<a href="#step-3-state-channel-update" class="hash-link" aria-label="Direct link to Step 3: State Channel Update" title="Direct link to Step 3: State Channel Update"></a></h5><p>If accepted:</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Requester:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 1. Load existing state channel with Provider</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 2. Create new state with updated balance</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 3. Sign state update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 4. Encode as JSON</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Requester → Provider: Message(payment: StateChannelUpdate(update=<signed JSON>))</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="step-4-payment-verification">Step 4: Payment Verification<a href="#step-4-payment-verification" class="hash-link" aria-label="Direct link to Step 4: Payment Verification" title="Direct link to Step 4: Payment Verification"></a></h5><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Provider:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 1. Decode state channel update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 2. Verify signatures</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 3. Check balance increase matches price</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 4. Verify state channel validity</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 5. Check nonce/sequence number</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">If valid:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Provider → Requester: BlockDelivery(data, proof)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">Else:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> Provider → Requester: BlockPresence(price) // Retry with correct payment</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h5 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="step-5-delivery-and-finalization">Step 5: Delivery and Finalization<a href="#step-5-delivery-and-finalization" class="hash-link" aria-label="Direct link to Step 5: Delivery and Finalization" title="Direct link to Step 5: Delivery and Finalization"></a></h5><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Requester:</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 1. Receive and verify block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 2. Store block locally</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 3. Finalize state channel update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> 4. Update peer credit balance</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="payment-state-machine">Payment State Machine<a href="#payment-state-machine" class="hash-link" aria-label="Direct link to Payment State Machine" title="Direct link to Payment State Machine"></a></h4><p><strong>Note:</strong> The following state machine represents a <strong>design specification</strong> for
|
||
payment flow logic. Actual implementation may differ.</p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: INIT</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Send wantHave</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Transition to PRICE_DISCOVERY</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: PRICE_DISCOVERY</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ← Receive BlockPresence(price)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → If price acceptable: Transition to PAYMENT_CREATION</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → If price rejected: Transition to CANCELLED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: PAYMENT_CREATION</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Create state channel update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Send payment message</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Transition to PAYMENT_PENDING</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: PAYMENT_PENDING</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ← Receive BlockDelivery: Transition to DELIVERY_VERIFICATION</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ← Receive BlockPresence(price): Transition to PAYMENT_FAILED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: PAYMENT_FAILED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Retry with corrected payment: Transition to PAYMENT_CREATION</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Abort: Transition to CANCELLED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: DELIVERY_VERIFICATION</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Verify block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → If valid: Transition to COMPLETED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → If invalid: Transition to DISPUTE</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: COMPLETED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Finalize state channel</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → End</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: CANCELLED</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Send cancellation</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → End</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">State: DISPUTE</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Reject block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → Dispute state channel update</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> → End</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="state-channel-integration">State Channel Integration<a href="#state-channel-integration" class="hash-link" aria-label="Direct link to State Channel Integration" title="Direct link to State Channel Integration"></a></h4><p><strong>Account Message Usage:</strong></p><p>Sent early in connection to establish payment address:</p><div class="language-protobuf codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-protobuf codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">Message {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> account: AccountMessage {</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> address: 0x742d35Cc6634C0532925a3b8... // Ethereum address</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> }</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>State Channel Update Format:</strong></p><div class="language-json codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-json codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">"channelId"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x1234..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">"nonce"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token number">42</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">"balances"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">"0x742d35Cc..."</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"1000000000000000000"</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Seller balance</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">"0x8ab5d2F3..."</span><span class="token operator">:</span><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"500000000000000000"</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Buyer balance</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token property">"signatures"</span><span class="token operator">:</span><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x789abc..."</span><span class="token punctuation" style="color:rgb(248, 248, 242)">,</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Buyer signature</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token string" style="color:rgb(255, 121, 198)">"0x456def..."</span><span class="token plain"> </span><span class="token comment" style="color:rgb(98, 114, 164)">// Seller signature</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> </span><span class="token punctuation" style="color:rgb(248, 248, 242)">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"></span><span class="token punctuation" style="color:rgb(248, 248, 242)">}</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="error-scenarios">Error Scenarios<a href="#error-scenarios" class="hash-link" aria-label="Direct link to Error Scenarios" title="Direct link to Error Scenarios"></a></h4><p><strong>Insufficient Funds:</strong></p><ul><li>State channel balance < block price</li><li>Response: BlockPresence with price (retry after funding)</li></ul><p><strong>Invalid Signature:</strong></p><ul><li>State update signature verification fails</li><li>Response: Reject payment, close stream if repeated</li></ul><p><strong>Nonce Mismatch:</strong></p><ul><li>State update nonce doesn't match expected sequence</li><li>Response: Request state sync, retry with correct nonce</li></ul><p><strong>Channel Expired:</strong></p><ul><li>State channel past expiration time</li><li>Response: Refuse payment, request new channel creation</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="error-handling">Error Handling<a href="#error-handling" class="hash-link" aria-label="Direct link to Error Handling" title="Direct link to Error Handling"></a></h2><p>The Block Exchange protocol defines error handling for common failure scenarios:</p><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="verification-failures">Verification Failures<a href="#verification-failures" class="hash-link" aria-label="Direct link to Verification Failures" title="Direct link to Verification Failures"></a></h3><p><strong>Merkle Proof Verification Failure:</strong></p><ul><li><strong>Condition</strong>: CodexProof validation fails for dataset block</li><li><strong>Action</strong>: Reject block delivery, do NOT store block</li><li><strong>Response</strong>: Send BlockPresence with <code>presenceDontHave</code> for the address</li><li><strong>Logging</strong>: Log verification failure with peer ID and block address</li><li><strong>Peer Management</strong>: Track repeated failures; disconnect after threshold</li></ul><p><strong>CID Mismatch:</strong></p><ul><li><strong>Condition</strong>: SHA256 hash of block data doesn't match provided CID</li><li><strong>Action</strong>: Reject block delivery immediately</li><li><strong>Response</strong>: Close stream and mark peer as potentially malicious</li><li><strong>Logging</strong>: Log CID mismatch with peer ID and expected/actual CIDs</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="network-failures">Network Failures<a href="#network-failures" class="hash-link" aria-label="Direct link to Network Failures" title="Direct link to Network Failures"></a></h3><p><strong>Stream Disconnection:</strong></p><ul><li><strong>Condition</strong>: libp2p stream closes unexpectedly during transfer</li><li><strong>Action</strong>: Cancel pending block requests for that peer</li><li><strong>Recovery</strong>: Attempt to request blocks from alternative peers</li><li><strong>Timeout</strong>: Wait for stream timeout (60s) before peer cleanup</li></ul><p><strong>Missing Blocks:</strong></p><ul><li><strong>Condition</strong>: Peer responds with <code>presenceDontHave</code> for requested block</li><li><strong>Action</strong>: Remove peer from candidates for this block</li><li><strong>Recovery</strong>: Query discovery service for alternative peers</li><li><strong>Fallback</strong>: If no peers have block, return error to <code>requestBlock</code> caller</li></ul><p><strong>Request Timeout:</strong></p><ul><li><strong>Condition</strong>: Block not received within request timeout (300s)</li><li><strong>Action</strong>: Cancel request with that peer</li><li><strong>Recovery</strong>: Retry with different peer if available</li><li><strong>User Notification</strong>: If all retry attempts exhausted, <code>requestBlock</code> returns timeout error</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="protocol-violations">Protocol Violations<a href="#protocol-violations" class="hash-link" aria-label="Direct link to Protocol Violations" title="Direct link to Protocol Violations"></a></h3><p><strong>Oversized Messages:</strong></p><ul><li><strong>Condition</strong>: Message exceeds maximum size limits</li><li><strong>Action</strong>: Close stream immediately</li><li><strong>Peer Management</strong>: Mark peer as non-compliant</li><li><strong>No Response</strong>: Do not send error message (message may be malicious)</li></ul><p><strong>Invalid WantList:</strong></p><ul><li><strong>Condition</strong>: WantList exceeds entry limit or contains malformed addresses</li><li><strong>Action</strong>: Ignore malformed entries, process valid ones</li><li><strong>Response</strong>: Continue processing stream</li><li><strong>Logging</strong>: Log validation errors for debugging</li></ul><p><strong>Payment Failures:</strong></p><ul><li><strong>Condition</strong>: State channel update invalid or payment insufficient</li><li><strong>Action</strong>: Do not deliver blocks requiring payment</li><li><strong>Response</strong>: Send BlockPresence with price indicating payment needed</li><li><strong>Stream</strong>: Keep stream open for payment retry</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="recovery-strategies">Recovery Strategies<a href="#recovery-strategies" class="hash-link" aria-label="Direct link to Recovery Strategies" title="Direct link to Recovery Strategies"></a></h3><h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="retry-responsibility-model">Retry Responsibility Model<a href="#retry-responsibility-model" class="hash-link" aria-label="Direct link to Retry Responsibility Model" title="Direct link to Retry Responsibility Model"></a></h4><p>The protocol defines a clear separation between system-level and caller-level
|
||
retry responsibilities:</p><p><strong>System-Level Retry (Automatic):</strong></p><p>The Block Exchange module automatically retries in these scenarios:</p><ul><li><strong>Peer failure</strong>: If a peer disconnects or times out, the system
|
||
transparently tries alternative peers from the discovery set</li><li><strong>Transient errors</strong>: Network glitches, temporary unavailability</li><li><strong>Peer rotation</strong>: Automatic failover to next available peer</li></ul><p>The caller's <code>requestBlock</code> call remains pending during system-level retries.
|
||
This is transparent to the caller.</p><p><strong>Caller-Level Retry (Manual):</strong></p><p>The caller is responsible for retry decisions when:</p><ul><li><strong>All peers exhausted</strong>: No more peers available from discovery</li><li><strong>Permanent failures</strong>: Block doesn't exist in the network</li><li><strong>Timeout exceeded</strong>: Request timeout (300s) expired</li><li><strong>Verification failures</strong>: All peers provided invalid data</li></ul><p>In these cases, <code>requestBlock</code> returns an error and the caller decides
|
||
whether to retry, perhaps after waiting or refreshing the peer list
|
||
via discovery.</p><p><strong>Retry Flow:</strong></p><div class="language-text codeBlockContainer_EB2s codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#F8F8F2;--prism-background-color:rgba(var(--lsd-surface-secondary), 0.08)"><div class="codeBlockContent_ugSV"><pre tabindex="0" class="prism-code language-text codeBlock_TWhw thin-scrollbar"><code class="codeBlockLines_LDrR"><span class="token-line" style="color:#F8F8F2"><span class="token plain">requestBlock(address)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> ├─► System tries Peer A ──► Fails</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ └─► System tries Peer B ──► Fails (automatic, transparent)</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │ └─► System tries Peer C ──► Success ──► Return block</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> └─► All peers failed ──► Return error to caller</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> │</span><br></span><span class="token-line" style="color:#F8F8F2"><span class="token plain"> └─► Caller decides: retry? wait? abort?</span><br></span></code></pre><div class="buttonGroup_Qu4e"><button type="button" aria-label="Copy code to clipboard" title="Copy" class="clean-btn"><span class="copyButtonIcons_an20" aria-hidden="true"><div class="icon_S7Kx m_thRi copyButtonIcon_ZL7v"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M2.917 12.833c-.321 0-.596-.114-.825-.343a1.121 1.121 0 0 1-.342-.823V3.5h1.167v8.167h6.416v1.166H2.917ZM5.25 10.5c-.32 0-.596-.114-.824-.343a1.121 1.121 0 0 1-.343-.824v-7c0-.32.115-.595.343-.824.229-.229.504-.343.824-.342h5.25c.32 0 .596.114.824.343.229.228.343.503.343.823v7c0 .321-.115.596-.343.825a1.121 1.121 0 0 1-.824.342H5.25Zm0-1.167h5.25v-7H5.25v7Z" fill="#fff"></path></svg></div></span></button></div></div></div><p><strong>Peer Rotation:</strong></p><p>When a peer fails to deliver blocks:</p><ol><li>Mark peer as temporarily unavailable for this block</li><li>Query discovery service for alternative peers</li><li>Send WantList to new peers</li><li>Implement exponential backoff before retrying failed peer</li></ol><p><strong>Graceful Degradation:</strong></p><ul><li>If verification fails, request block from alternative peer</li><li>If all peers fail, propagate error to caller</li><li>Clean up resources (memory, pending requests) on unrecoverable failures</li></ul><p><strong>Error Propagation:</strong></p><ul><li>Service interface functions (<code>requestBlock</code>, <code>cancelRequest</code>) return errors
|
||
to callers only after system-level retries are exhausted</li><li>Internal errors logged for debugging</li><li>Network errors trigger automatic peer rotation before surfacing to caller</li><li>Verification errors result in block rejection and peer reputation impact</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="security-considerations">Security Considerations<a href="#security-considerations" class="hash-link" aria-label="Direct link to Security Considerations" title="Direct link to Security Considerations"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="block-verification">Block Verification<a href="#block-verification" class="hash-link" aria-label="Direct link to Block Verification" title="Direct link to Block Verification"></a></h3><ul><li>All dataset blocks MUST include and verify Merkle proofs before acceptance</li><li>Standalone blocks MUST verify CID matches the SHA256 hash of the data</li><li>Peers SHOULD reject blocks that fail verification immediately</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="dos-protection">DoS Protection<a href="#dos-protection" class="hash-link" aria-label="Direct link to DoS Protection" title="Direct link to DoS Protection"></a></h3><ul><li>Implementations SHOULD limit the number of concurrent block requests per peer</li><li>Implementations SHOULD implement rate limiting for WantList updates</li><li>Large WantLists MAY be rejected to prevent resource exhaustion</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="data-integrity">Data Integrity<a href="#data-integrity" class="hash-link" aria-label="Direct link to Data Integrity" title="Direct link to Data Integrity"></a></h3><ul><li>All blocks MUST be validated before being stored or forwarded</li><li>Zero-padding in dataset blocks MUST be verified to prevent data corruption</li><li>Block sizes MUST be validated against protocol limits</li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="privacy-considerations">Privacy Considerations<a href="#privacy-considerations" class="hash-link" aria-label="Direct link to Privacy Considerations" title="Direct link to Privacy Considerations"></a></h3><ul><li>Block requests reveal information about what data a peer is seeking</li><li>Implementations MAY implement request obfuscation strategies</li><li>Presence information can leak storage capacity details</li></ul><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="rationale">Rationale<a href="#rationale" class="hash-link" aria-label="Direct link to Rationale" title="Direct link to Rationale"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="design-decisions">Design Decisions<a href="#design-decisions" class="hash-link" aria-label="Direct link to Design Decisions" title="Direct link to Design Decisions"></a></h3><p><strong>Two-Tier Block Addressing:</strong>
|
||
The protocol supports both standalone and dataset blocks to accommodate
|
||
different use cases.
|
||
Standalone blocks are simpler and don't require Merkle proofs, while
|
||
dataset blocks enable efficient verification of large datasets without
|
||
requiring the entire dataset.</p><p><strong>WantList Delta Updates:</strong>
|
||
Supporting delta updates reduces bandwidth consumption when peers only
|
||
need to modify a small portion of their wants, which is common in
|
||
long-lived connections.</p><p><strong>Separate Presence Messages:</strong>
|
||
Decoupling presence information from block delivery allows peers to
|
||
quickly assess availability without waiting for full block transfers.</p><p><strong>Fixed Block Size:</strong>
|
||
The 64 KiB default block size balances efficient network transmission
|
||
with manageable memory overhead.</p><p><strong>Zero-Padding Requirement:</strong>
|
||
Requiring zero-padding for incomplete dataset blocks ensures uniform
|
||
block sizes within datasets, simplifying Merkle tree construction and
|
||
verification.</p><p><strong>Protocol Buffers:</strong>
|
||
Using Protocol Buffers provides efficient serialization, forward
|
||
compatibility, and wide language support.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="copyright">Copyright<a href="#copyright" class="hash-link" aria-label="Direct link to Copyright" title="Direct link to Copyright"></a></h2><p>Copyright and related rights waived via
|
||
<a href="https://creativecommons.org/publicdomain/zero/1.0/" target="_blank" rel="noopener noreferrer">CC0</a>.</p><h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="references">References<a href="#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References"></a></h2><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="normative">Normative<a href="#normative" class="hash-link" aria-label="Direct link to Normative" title="Direct link to Normative"></a></h3><ul><li><a href="https://www.ietf.org/rfc/rfc2119.txt" target="_blank" rel="noopener noreferrer">RFC 2119</a> - Key words for use
|
||
in RFCs to Indicate Requirement Levels</li><li><strong>libp2p</strong>: <<a href="https://libp2p.io" target="_blank" rel="noopener noreferrer">https://libp2p.io</a>></li><li><strong>Protocol Buffers</strong>: <<a href="https://protobuf.dev" target="_blank" rel="noopener noreferrer">https://protobuf.dev</a>></li><li><strong>Multihash</strong>: <<a href="https://multiformats.io/multihash/" target="_blank" rel="noopener noreferrer">https://multiformats.io/multihash/</a>></li><li><strong>Multicodec</strong>: <<a href="https://github.com/multiformats/multicodec" target="_blank" rel="noopener noreferrer">https://github.com/multiformats/multicodec</a>></li></ul><h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="informative">Informative<a href="#informative" class="hash-link" aria-label="Direct link to Informative" title="Direct link to Informative"></a></h3><ul><li><strong>Codex Documentation</strong>: <<a href="https://docs.codex.storage" target="_blank" rel="noopener noreferrer">https://docs.codex.storage</a>></li><li><strong>Codex Block Exchange Module Spec</strong>:
|
||
<<a href="https://github.com/codex-storage/codex-docs-obsidian/blob/main/10%20Notes/Specs/Block%20Exchange%20Module%20Spec.md" target="_blank" rel="noopener noreferrer">https://github.com/codex-storage/codex-docs-obsidian/blob/main/10%20Notes/Specs/Block%20Exchange%20Module%20Spec.md</a>></li><li><strong>Merkle Trees</strong>: <<a href="https://en.wikipedia.org/wiki/Merkle_tree" target="_blank" rel="noopener noreferrer">https://en.wikipedia.org/wiki/Merkle_tree</a>></li><li><strong>Content Addressing</strong>:
|
||
<<a href="https://en.wikipedia.org/wiki/Content-addressable_storage" target="_blank" rel="noopener noreferrer">https://en.wikipedia.org/wiki/Content-addressable_storage</a>></li></ul></div></article><nav class="pagination-nav docusaurus-mt-lg" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/codex/"><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="M11.667 6.417h-7.1l3.261-3.261L7 2.333 2.333 7 7 11.667l.823-.823-3.255-3.26h7.099V6.417Z" fill="#fff"></path></svg></div><span class="lsd-typography lsd-typography--body2 pagination-nav__label">Codex RFCs</span></a><a class="pagination-nav__link pagination-nav__link--next" href="/codex/raw/codex-marketplace"><span class="lsd-typography lsd-typography--body2 pagination-nav__label">CODEX-MARKETPLACE</span><div class="icon_S7Kx m_thRi"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg" role="img"><path d="m7 2.333-.823.823 3.255 3.26H2.333v1.167h7.1l-3.256 3.261.823.823L11.667 7 7 2.333Z" fill="#fff"></path></svg></div></a></nav></div></div><div class="gap1_XuuQ"></div><div class="toc_pP_5"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#specification-status" class="table-of-contents__link toc-highlight">Specification Status</a></li><li><a href="#abstract" class="table-of-contents__link toc-highlight">Abstract</a></li><li><a href="#semantics" class="table-of-contents__link toc-highlight">Semantics</a><ul><li><a href="#definitions" class="table-of-contents__link toc-highlight">Definitions</a></li></ul></li><li><a href="#motivation" class="table-of-contents__link toc-highlight">Motivation</a></li><li><a href="#block-format" class="table-of-contents__link toc-highlight">Block Format</a><ul><li><a href="#standalone-blocks" class="table-of-contents__link toc-highlight">Standalone Blocks</a></li><li><a href="#dataset-blocks" class="table-of-contents__link toc-highlight">Dataset Blocks</a></li><li><a href="#block-specifications" class="table-of-contents__link toc-highlight">Block Specifications</a></li><li><a href="#protocol-limits" class="table-of-contents__link toc-highlight">Protocol Limits</a></li></ul></li><li><a href="#service-interface" class="table-of-contents__link toc-highlight">Service Interface</a><ul><li><a href="#requestblock" class="table-of-contents__link toc-highlight"><code>requestBlock</code></a></li><li><a href="#cancelrequest" class="table-of-contents__link toc-highlight"><code>cancelRequest</code></a></li></ul></li><li><a href="#dependencies" class="table-of-contents__link toc-highlight">Dependencies</a></li><li><a href="#protocol-specification" class="table-of-contents__link toc-highlight">Protocol Specification</a><ul><li><a href="#protocol-identifier" class="table-of-contents__link toc-highlight">Protocol Identifier</a></li><li><a href="#version-negotiation" class="table-of-contents__link toc-highlight">Version Negotiation</a></li><li><a href="#connection-model" class="table-of-contents__link toc-highlight">Connection Model</a></li><li><a href="#message-flow-examples" class="table-of-contents__link toc-highlight">Message Flow Examples</a></li><li><a href="#sequence-diagrams" class="table-of-contents__link toc-highlight">Sequence Diagrams</a></li><li><a href="#message-format" class="table-of-contents__link toc-highlight">Message Format</a></li><li><a href="#concrete-message-examples" class="table-of-contents__link toc-highlight">Concrete Message Examples</a></li><li><a href="#payment-flow-and-price-negotiation" class="table-of-contents__link toc-highlight">Payment Flow and Price Negotiation</a></li></ul></li><li><a href="#error-handling" class="table-of-contents__link toc-highlight">Error Handling</a><ul><li><a href="#verification-failures" class="table-of-contents__link toc-highlight">Verification Failures</a></li><li><a href="#network-failures" class="table-of-contents__link toc-highlight">Network Failures</a></li><li><a href="#protocol-violations" class="table-of-contents__link toc-highlight">Protocol Violations</a></li><li><a href="#recovery-strategies" class="table-of-contents__link toc-highlight">Recovery Strategies</a></li></ul></li><li><a href="#security-considerations" class="table-of-contents__link toc-highlight">Security Considerations</a><ul><li><a href="#block-verification" class="table-of-contents__link toc-highlight">Block Verification</a></li><li><a href="#dos-protection" class="table-of-contents__link toc-highlight">DoS Protection</a></li><li><a href="#data-integrity" class="table-of-contents__link toc-highlight">Data Integrity</a></li><li><a href="#privacy-considerations" class="table-of-contents__link toc-highlight">Privacy Considerations</a></li></ul></li><li><a href="#rationale" class="table-of-contents__link toc-highlight">Rationale</a><ul><li><a href="#design-decisions" class="table-of-contents__link toc-highlight">Design Decisions</a></li></ul></li><li><a href="#copyright" class="table-of-contents__link toc-highlight">Copyright</a></li><li><a href="#references" class="table-of-contents__link toc-highlight">References</a><ul><li><a href="#normative" class="table-of-contents__link toc-highlight">Normative</a></li><li><a href="#informative" class="table-of-contents__link toc-highlight">Informative</a></li></ul></li></ul></div></div></div></div></main></div></div><footer class="footer"><div class="container container-fluid firstRow_ar1q"><div class="footer__bottom text--center"><div class="margin-bottom--sm"><a class="footerLogoLink_BH7S" href="/"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--light_BL8e footer__logo" width="22"><img src="/theme/image/logo.svg" alt="Vac Research" class="themedImage_kfRS themedImage--dark_OvIx footer__logo" width="22"></a></div><div class="footer__copyright">Vac @2025<br>All Rights Reserved.</div></div><div class="row footer__links"><div class="col footer__col"><div class="footer__title"></div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://x.com/vacp2p" target="_blank" rel="noopener noreferrer" class="footer__link-item">Twitter<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://discord.gg/PQFdubGt6d" target="_blank" rel="noopener noreferrer" class="footer__link-item">Discord<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://github.com/vacp2p" target="_blank" rel="noopener noreferrer" class="footer__link-item">Github<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title"></div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://jobs.status.im/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Work with us<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a class="footer__link-item" href="/terms">Terms & conditions</a></li><li class="footer__item"><a class="footer__link-item" href="/privacy-policy">Privacy Policy</a></li><li class="footer__item"><a class="footer__link-item" href="/security">Security</a></li></ul></div></div></div><div class="secondRow__ww3"><span class="footer__bottom text--center">Built by <a href="https://free.technology/" target="_blank" class="footerLink_sh7M">IFT</a></span><div class="row footer__links"><div class="col footer__col"><div class="footer__title">Research</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://vac.dev" target="_blank" rel="noopener noreferrer" class="footer__link-item">VacP2P<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://afaik.institute" target="_blank" rel="noopener noreferrer" class="footer__link-item">AFAIK<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">Infrastructure</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://waku.org/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Waku<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://nimbus.team/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Nimbus<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://codex.storage" target="_blank" rel="noopener noreferrer" class="footer__link-item">Codex<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://nomos.tech" target="_blank" rel="noopener noreferrer" class="footer__link-item">Nomos<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">Creative Studio</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://acid.info" target="_blank" rel="noopener noreferrer" class="footer__link-item">Acid.info<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">Movement</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://logos.co" target="_blank" rel="noopener noreferrer" class="footer__link-item">Logos<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div><div class="col footer__col"><div class="footer__title">User-facing products</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://status.im" target="_blank" rel="noopener noreferrer" class="footer__link-item">Status<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li><li class="footer__item"><a href="https://keycard.tech" target="_blank" rel="noopener noreferrer" class="footer__link-item">Keycard<svg width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" class="iconExternalLink_nPIU"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path></svg></a></li></ul></div></div></div><button class="backToTop_wDfN lsd-button lsd-button--small lsd-button--outlined"><span class="lsd-typography lsd-typography--label2 lsd-button__text">Back to top ↑</span></button></footer></div></div>
|
||
<script src="/assets/js/runtime~main.db01e95f.js"></script>
|
||
<script src="/assets/js/main.7bd63d25.js"></script>
|
||
</body>
|
||
</html> |