Commit b7087214 authored by norswap's avatar norswap Committed by GitHub

spec: derivation spec rework (#2855)

* batch derivation spec draft

* add diagrams, fix recovery-from-reorg wording

* update spec to cover channel ID timestamp

* specs: update batch derivation diagrams

* simplified overview draft + greatly expand glossary

* section on batch submission an encoding

* stages explanation

* edit resetting part of the spec

* rework pipeline description (& more)

* incorporate review feedback

* recover lost change

* rework payload attributes derivation section

* specs: toc fix

* specs: misc lint fixes

* specs/meta: toc fix
Co-authored-by: default avatarprotolambda <proto@protolambda.com>
Co-authored-by: default avatarmergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
parent aa707a47
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="10662px" height="6124px" viewBox="-0.5 -0.5 10662 6124"><defs><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-75acff-1-ff66b3-1-e-0"><stop offset="0%" style="stop-color: rgb(117, 172, 255); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(255, 102, 179); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-ffe563-1-8cffb6-1-e-0"><stop offset="0%" style="stop-color: rgb(255, 229, 99); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(140, 255, 182); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-75acff-1-c683d2-1-e-0"><stop offset="0%" style="stop-color: rgb(117, 172, 255); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(198, 131, 210); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-ffe563-1-d8ea7c-1-e-0"><stop offset="0%" style="stop-color: rgb(255, 229, 99); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(216, 234, 124); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-d8ea7c-1-b0f79c-1-e-0"><stop offset="0%" style="stop-color: rgb(216, 234, 124); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(176, 247, 156); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-c683d2-1-ff66b3-1-e-0"><stop offset="0%" style="stop-color: rgb(198, 131, 210); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(255, 102, 179); stop-opacity: 1;"/></linearGradient><linearGradient x1="0%" y1="0%" x2="100%" y2="0%" id="mx-gradient-b0f79c-1-8cffb6-1-e-0"><stop offset="0%" style="stop-color: rgb(176, 247, 156); stop-opacity: 1;"/><stop offset="100%" style="stop-color: rgb(140, 255, 182); stop-opacity: 1;"/></linearGradient></defs><g><path d="M 3900 20 L 4300 20 L 4380 100 L 4380 500 L 3980 500 L 3900 420 L 3900 20 Z" fill="#ff0080" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 3900 20 L 4300 20 L 4380 100 L 3980 100 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 3900 20 L 3980 100 L 3980 500 L 3900 420 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 3980 500 L 3980 100 L 3900 20 M 3980 100 L 4380 100" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 111px; margin-left: 1006px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="1082" y="111" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">100</text></switch></g><path d="M 7420 20 L 7820 20 L 7900 100 L 7900 500 L 7500 500 L 7420 420 L 7420 20 Z" fill="#ccffff" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 7420 20 L 7820 20 L 7900 100 L 7500 100 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 7420 20 L 7500 100 L 7500 500 L 7420 420 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 7500 500 L 7500 100 L 7420 20 M 7500 100 L 7900 100" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 111px; margin-left: 1886px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">102</div></div></div></foreignObject><text x="1962" y="111" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">102</text></switch></g><path d="M 5540 20 L 5940 20 L 6020 100 L 6020 500 L 5620 500 L 5540 420 L 5540 20 Z" fill="#ffff66" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 5540 20 L 5940 20 L 6020 100 L 5620 100 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 5540 20 L 5620 100 L 5620 500 L 5540 420 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 5620 500 L 5620 100 L 5540 20 M 5620 100 L 6020 100" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 111px; margin-left: 1416px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">101</div></div></div></foreignObject><text x="1492" y="111" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">101</text></switch></g><path d="M 3600 4420 L 4000 4420 L 4080 4500 L 4080 4900 L 3680 4900 L 3600 4820 L 3600 4420 Z" fill="#ccccff" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 3600 4420 L 4000 4420 L 4080 4500 L 3680 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 3600 4420 L 3680 4500 L 3680 4900 L 3600 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 3680 4900 L 3680 4500 L 3600 4420 M 3680 4500 L 4080 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 931px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">3</div></div></div></foreignObject><text x="1007" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">3</text></switch></g><path d="M 4240 4420 L 4640 4420 L 4720 4500 L 4720 4900 L 4320 4900 L 4240 4820 L 4240 4420 Z" fill="#75acff" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 4240 4420 L 4640 4420 L 4720 4500 L 4320 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 4240 4420 L 4320 4500 L 4320 4900 L 4240 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 4320 4900 L 4320 4500 L 4240 4420 M 4320 4500 L 4720 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 1091px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">4</div></div></div></foreignObject><text x="1167" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">4</text></switch></g><path d="M 4880 4420 L 5280 4420 L 5360 4500 L 5360 4900 L 4960 4900 L 4880 4820 L 4880 4420 Z" fill="#c882d1" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 4880 4420 L 5280 4420 L 5360 4500 L 4960 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 4880 4420 L 4960 4500 L 4960 4900 L 4880 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 4960 4900 L 4960 4500 L 4880 4420 M 4960 4500 L 5360 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 1251px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">5</div></div></div></foreignObject><text x="1327" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">5</text></switch></g><path d="M 5520 4420 L 5920 4420 L 6000 4500 L 6000 4900 L 5600 4900 L 5520 4820 L 5520 4420 Z" fill="#ff66b3" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 5520 4420 L 5920 4420 L 6000 4500 L 5600 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 5520 4420 L 5600 4500 L 5600 4900 L 5520 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 5600 4900 L 5600 4500 L 5520 4420 M 5600 4500 L 6000 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 1411px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">6</div></div></div></foreignObject><text x="1487" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">6</text></switch></g><path d="M 6160 4420 L 6560 4420 L 6640 4500 L 6640 4900 L 6240 4900 L 6160 4820 L 6160 4420 Z" fill="#ffae52" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 6160 4420 L 6560 4420 L 6640 4500 L 6240 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 6160 4420 L 6240 4500 L 6240 4900 L 6160 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 6240 4900 L 6240 4500 L 6160 4420 M 6240 4500 L 6640 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 1571px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">7</div></div></div></foreignObject><text x="1647" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">7</text></switch></g><path d="M 6800 4420 L 7200 4420 L 7280 4500 L 7280 4900 L 6880 4900 L 6800 4820 L 6800 4420 Z" fill="#ffffa1" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 6800 4420 L 7200 4420 L 7280 4500 L 6880 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 6800 4420 L 6880 4500 L 6880 4900 L 6800 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 6880 4900 L 6880 4500 L 6800 4420 M 6880 4500 L 7280 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 1731px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">8</div></div></div></foreignObject><text x="1807" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">8</text></switch></g><rect x="3600" y="3940" width="480" height="240" rx="36" ry="36" fill="#ccccff" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="4240" y="3940" width="480" height="240" rx="36" ry="36" fill="#75acff" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="4880" y="3940" width="480" height="240" rx="36" ry="36" fill="#c882d1" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="5520" y="3940" width="480" height="240" rx="36" ry="36" fill="#ff66b3" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="6160" y="3940" width="480" height="240" rx="36" ry="36" fill="#ffae52" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="6800" y="3940" width="480" height="240" rx="36" ry="36" fill="#ffffa1" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="3600" y="3500" width="2400" height="240" fill="url(#mx-gradient-75acff-1-ff66b3-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 598px; height: 1px; padding-top: 905px; margin-left: 901px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 25px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-style: italic; white-space: normal; overflow-wrap: normal;">Compressed &amp; encoded batch data</div></div></div></foreignObject><text x="1200" y="912" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="25px" text-anchor="middle" font-style="italic">Compressed &amp; encoded batch data</text></switch></g><rect x="6080" y="3500" width="3040" height="240" fill="url(#mx-gradient-ffe563-1-8cffb6-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="3600" y="3060" width="1440" height="240" fill="url(#mx-gradient-75acff-1-c683d2-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 332px; height: 1px; padding-top: 815px; margin-left: 907px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">A0</div></div></div></foreignObject><text x="1239" y="815" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">A0</text></switch></g><rect x="6080" y="3060" width="480" height="240" fill="url(#mx-gradient-ffe563-1-d8ea7c-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 92px; height: 1px; padding-top: 815px; margin-left: 1527px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">B0</div></div></div></foreignObject><text x="1619" y="815" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">B0</text></switch></g><rect x="6640" y="3060" width="1440" height="240" fill="url(#mx-gradient-d8ea7c-1-b0f79c-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 332px; height: 1px; padding-top: 815px; margin-left: 1667px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">B1</div></div></div></foreignObject><text x="1999" y="815" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">B1</text></switch></g><rect x="9280" y="3060" width="320" height="240" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><path d="M 7440 4420 L 7840 4420 L 7920 4500 L 7920 4900 L 7520 4900 L 7440 4820 L 7440 4420 Z" fill="#c3ffa1" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 7440 4420 L 7840 4420 L 7920 4500 L 7520 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 7440 4420 L 7520 4500 L 7520 4900 L 7440 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 7520 4900 L 7520 4500 L 7440 4420 M 7520 4500 L 7920 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 1891px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">9</div></div></div></foreignObject><text x="1967" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">9</text></switch></g><path d="M 8080 4420 L 8480 4420 L 8560 4500 L 8560 4900 L 8160 4900 L 8080 4820 L 8080 4420 Z" fill="#97ff63" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 8080 4420 L 8480 4420 L 8560 4500 L 8160 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 8080 4420 L 8160 4500 L 8160 4900 L 8080 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 8160 4900 L 8160 4500 L 8080 4420 M 8160 4500 L 8560 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 2051px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">10</div></div></div></foreignObject><text x="2127" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">10</text></switch></g><path d="M 8720 4420 L 9120 4420 L 9200 4500 L 9200 4900 L 8800 4900 L 8720 4820 L 8720 4420 Z" fill="#8cffb6" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 8720 4420 L 9120 4420 L 9200 4500 L 8800 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 8720 4420 L 8800 4500 L 8800 4900 L 8720 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 8800 4900 L 8800 4500 L 8720 4420 M 8800 4500 L 9200 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 1211px; margin-left: 2211px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">11</div></div></div></foreignObject><text x="2287" y="1211" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">11</text></switch></g><path d="M 9360 4420 L 9760 4420 L 9840 4500 L 9840 4900 L 9440 4900 L 9360 4820 L 9360 4420 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 9360 4420 L 9760 4420 L 9840 4500 L 9440 4500 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 9360 4420 L 9440 4500 L 9440 4900 L 9360 4820 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 9440 4900 L 9440 4500 L 9360 4420 M 9440 4500 L 9840 4500" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><rect x="7440" y="3940" width="480" height="240" rx="36" ry="36" fill="#c3ffa1" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="8080" y="3940" width="480" height="240" rx="36" ry="36" fill="#97ff63" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="8720" y="3940" width="480" height="240" rx="36" ry="36" fill="#8cffb6" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="9360" y="3940" width="480" height="240" rx="36" ry="36" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="5120" y="3060" width="960" height="240" fill="url(#mx-gradient-c683d2-1-ff66b3-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 212px; height: 1px; padding-top: 815px; margin-left: 1287px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">A1</div></div></div></foreignObject><text x="1499" y="815" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">A1</text></switch></g><rect x="8160" y="3060" width="1120" height="240" fill="url(#mx-gradient-b0f79c-1-8cffb6-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 252px; height: 1px; padding-top: 815px; margin-left: 2047px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">B2</div></div></div></foreignObject><text x="2299" y="815" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">B2</text></switch></g><rect x="9200" y="3500" width="760" height="240" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="9840" y="3140" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10010" y="3140" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10170" y="3140" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10090" y="3580" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10260" y="3580" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10420" y="3580" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10010" y="4020" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10180" y="4020" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10340" y="4020" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="9960" y="4620" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10130" y="4620" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="10290" y="4620" width="60" height="80" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="2600" y="3060" width="760" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 795px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">L1 Transactions,<br /> ~128 KB each</div></div></div></foreignObject><text x="838" y="801" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">L1 Transactions,...</text></switch></g><rect x="2760" y="3500" width="600" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 905px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Channels,<br />with timeout</div></div></div></foreignObject><text x="838" y="911" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">Channels,...</text></switch></g><rect x="2240" y="3940" width="1120" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 1015px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Batches,<br />1 batch = 1 L2 block tx list</div></div></div></foreignObject><text x="838" y="1021" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">Batches,...</text></switch></g><rect x="2240" y="4520" width="1120" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 1160px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">L2 Blocks<br />(a.k.a. execution payloads)</div></div></div></foreignObject><text x="838" y="1166" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">L2 Blocks...</text></switch></g><rect x="3920" y="2860" width="800" height="120" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 730px; margin-left: 1080px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Channel A, Frame 0</div></div></div></foreignObject><text x="1080" y="736" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="middle">Channel A, Frame 0</text></switch></g><rect x="5140" y="2860" width="800" height="120" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 730px; margin-left: 1385px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Channel A, Frame 1</div></div></div></foreignObject><text x="1385" y="736" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="middle">Channel A, Frame 1</text></switch></g><rect x="6100" y="2740" width="480" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 715px; margin-left: 1585px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Channel B,<br /> Frame 0</div></div></div></foreignObject><text x="1585" y="721" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="middle">Channel B,...</text></switch></g><rect x="6960" y="2860" width="800" height="120" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 730px; margin-left: 1840px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Channel B, Frame 1</div></div></div></foreignObject><text x="1840" y="736" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="middle">Channel B, Frame 1</text></switch></g><rect x="8300" y="2860" width="800" height="120" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 730px; margin-left: 2175px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Channel B, Frame 2</div></div></div></foreignObject><text x="2175" y="736" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="middle">Channel B, Frame 2</text></switch></g><rect x="9410" y="2860" width="680" height="120" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 730px; margin-left: 2438px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Channel C, etc...</div></div></div></foreignObject><text x="2438" y="736" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="middle">Channel C, etc...</text></switch></g><rect x="8700" y="40" width="880" height="440" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 65px; margin-left: 2177px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">L1 Blocks,<br />These may not be as<br />frequent/consistent<br /> as L2 blocks.</div></div></div></foreignObject><text x="2177" y="71" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" font-weight="bold">L1 Blocks,...</text></switch></g><rect x="8700" y="660" width="1000" height="320" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 205px; margin-left: 2177px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Actual inclusion on L1:<br />channels are valid<br />within a timeout</div></div></div></foreignObject><text x="2177" y="211" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" font-weight="bold">Actual inclusion on L1:...</text></switch></g><rect x="8700" y="1180" width="1600" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 325px; margin-left: 2177px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Channel B was seen first,<br />and will be decoded into batches first.</div></div></div></foreignObject><text x="2177" y="331" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" font-weight="bold">Channel B was seen first,...</text></switch></g><rect x="3600" y="2020" width="480" height="240" rx="36" ry="36" fill="#ffae52" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="4240" y="2020" width="480" height="240" rx="36" ry="36" fill="#ffffa1" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="4880" y="2020" width="480" height="240" rx="36" ry="36" fill="#c3ffa1" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="5520" y="2020" width="480" height="240" rx="36" ry="36" fill="#97ff63" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="6160" y="2020" width="480" height="240" rx="36" ry="36" fill="#8cffb6" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="6800" y="2020" width="480" height="240" rx="36" ry="36" fill="#ccccff" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="7440" y="2020" width="480" height="240" rx="36" ry="36" fill="#75acff" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="8080" y="2020" width="480" height="240" rx="36" ry="36" fill="#c882d1" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="8720" y="2020" width="480" height="240" rx="36" ry="36" fill="#ff66b3" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="1920" y="1980" width="1440" height="440" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 550px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Batches can be buffered<br />for up to a full sequencing window<br />worth of L1 blocks<br />to get the L2 ordering back.</div></div></div></foreignObject><text x="838" y="556" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">Batches can be buffered...</text></switch></g><rect x="9220" y="5660" width="520" height="280" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 1450px; margin-left: 2433px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 50px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Time</div></div></div></foreignObject><text x="2433" y="1465" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="50px" text-anchor="end" font-weight="bold">Time</text></switch></g><path d="M 9842 5800 L 9842 5760 L 10490 5760 L 10490 5648.91 L 10638 5780 L 10490 5911.09 L 10490 5800 Z" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><rect x="3540" y="700" width="1440" height="240" fill="#bfbfbf" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 358px; height: 1px; padding-top: 205px; margin-left: 886px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-style: italic; white-space: normal; overflow-wrap: normal;">older L2 data</div></div></div></foreignObject><text x="1065" y="214" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle" font-style="italic">older L2 data</text></switch></g><rect x="5260" y="700" width="1440" height="240" fill="url(#mx-gradient-d8ea7c-1-b0f79c-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 332px; height: 1px; padding-top: 225px; margin-left: 1322px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">B1</div></div></div></foreignObject><text x="1654" y="225" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">B1</text></switch></g><rect x="6220" y="1060" width="480" height="240" fill="url(#mx-gradient-ffe563-1-d8ea7c-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 92px; height: 1px; padding-top: 315px; margin-left: 1562px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">B0</div></div></div></foreignObject><text x="1654" y="315" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">B0</text></switch></g><rect x="5260" y="1060" width="960" height="240" fill="url(#mx-gradient-c683d2-1-ff66b3-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 212px; height: 1px; padding-top: 315px; margin-left: 1322px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">A1</div></div></div></foreignObject><text x="1534" y="315" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">A1</text></switch></g><rect x="8060" y="700" width="320" height="240" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><rect x="6940" y="700" width="1120" height="240" fill="url(#mx-gradient-b0f79c-1-8cffb6-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 252px; height: 1px; padding-top: 225px; margin-left: 1742px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">B2</div></div></div></foreignObject><text x="1994" y="225" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">B2</text></switch></g><rect x="6940" y="1060" width="1440" height="240" fill="url(#mx-gradient-75acff-1-c683d2-1-e-0)" stroke="rgb(0, 0, 0)" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 332px; height: 1px; padding-top: 315px; margin-left: 1742px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">A0</div></div></div></foreignObject><text x="2074" y="315" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="end">A0</text></switch></g><path d="M 6160 5420 L 6240 5180 L 6640 5180 L 6560 5420 Z" fill="#ff0080" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 1551px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100-0</div></div></div></foreignObject><text x="1647" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">100-0</text></switch></g><path d="M 6800 5420 L 6880 5180 L 7280 5180 L 7200 5420 Z" fill="#ff0080" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 1711px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100-1</div></div></div></foreignObject><text x="1807" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">100-1</text></switch></g><path d="M 7440 5420 L 7520 5180 L 7920 5180 L 7840 5420 Z" fill="#ff0080" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 1871px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100-2</div></div></div></foreignObject><text x="1967" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">100-2</text></switch></g><path d="M 8080 5420 L 8160 5180 L 8560 5180 L 8480 5420 Z" fill="#ff0080" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 2031px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100-3</div></div></div></foreignObject><text x="2127" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">100-3</text></switch></g><path d="M 8720 5420 L 8800 5180 L 9200 5180 L 9120 5420 Z" fill="#ff0080" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 2191px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100-2</div></div></div></foreignObject><text x="2287" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">100-2</text></switch></g><path d="M 9360 5420 L 9440 5180 L 9840 5180 L 9760 5420 Z" fill="#ffff66" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 2351px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">101-0</div></div></div></foreignObject><text x="2447" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">101-0</text></switch></g><path d="M 5520 5420 L 5600 5180 L 6000 5180 L 5920 5420 Z" fill="#e0e0e0" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 1391px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">99-5</div></div></div></foreignObject><text x="1487" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">99-5</text></switch></g><path d="M 4880 5420 L 4960 5180 L 5360 5180 L 5280 5420 Z" fill="#e0e0e0" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 1231px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">99-4</div></div></div></foreignObject><text x="1327" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">99-4</text></switch></g><path d="M 4240 5420 L 4320 5180 L 4720 5180 L 4640 5420 Z" fill="#e0e0e0" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 1071px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">99-3</div></div></div></foreignObject><text x="1167" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">99-3</text></switch></g><path d="M 3600 5420 L 3680 5180 L 4080 5180 L 4000 5420 Z" fill="#e0e0e0" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 96px; height: 1px; padding-top: 1341px; margin-left: 911px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">99-2</div></div></div></foreignObject><text x="1007" y="1341" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">99-2</text></switch></g><path d="M 2400 40 L 2800 40 L 2880 120 L 2880 520 L 2480 520 L 2400 440 L 2400 40 Z" fill="#e0e0e0" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><path d="M 2400 40 L 2800 40 L 2880 120 L 2480 120 Z" fill-opacity="0.05" fill="#000000" stroke="none" pointer-events="all"/><path d="M 2400 40 L 2480 120 L 2480 520 L 2400 440 Z" fill-opacity="0.1" fill="#000000" stroke="none" pointer-events="all"/><path d="M 2480 520 L 2480 120 L 2400 40 M 2480 120 L 2880 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 76px; height: 1px; padding-top: 116px; margin-left: 631px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">99</div></div></div></foreignObject><text x="707" y="116" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="end">99</text></switch></g><rect x="2040" y="5180" width="1320" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 1325px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Each L2 block has a tx with info<br />about the "origin" L1 block</div></div></div></foreignObject><text x="838" y="1331" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">Each L2 block has a tx with info...</text></switch></g><rect x="2040" y="5580" width="1320" height="320" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 1435px; margin-left: 838px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">The "sequence number" <br />helps differentiate between <br />L2 blocks with the same origin.</div></div></div></foreignObject><text x="838" y="1441" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">The "sequence number"...</text></switch></g><path d="M 3900 1100 Q 4080 1172 4260 1100 Q 4440 1028 4620 1100 L 4620 1300 Q 4440 1228 4260 1300 Q 4080 1372 3900 1300 L 3900 1100 Z" fill="#fff2cc" stroke="#d6b656" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 300px; margin-left: 976px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">deposit</div></div></div></foreignObject><text x="1065" y="309" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">deposit</text></switch></g><path d="M 3920 1380 Q 4100 1452 4280 1380 Q 4460 1308 4640 1380 L 4640 1580 Q 4460 1508 4280 1580 Q 4100 1652 3920 1580 L 3920 1380 Z" fill="#fff2cc" stroke="#d6b656" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 370px; margin-left: 981px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">deposit</div></div></div></foreignObject><text x="1070" y="379" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">deposit</text></switch></g><rect x="2180" y="1180" width="1160" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 325px; margin-left: 833px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Deposits are L1 log events,<br />parsed from EVM receipts</div></div></div></foreignObject><text x="833" y="331" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">Deposits are L1 log events,...</text></switch></g><path d="M 6100 5560 Q 6280 5632 6460 5560 Q 6640 5488 6820 5560 L 6820 5760 Q 6640 5688 6460 5760 Q 6280 5832 6100 5760 L 6100 5560 Z" fill="#fff2cc" stroke="#d6b656" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 1415px; margin-left: 1526px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">deposit</div></div></div></foreignObject><text x="1615" y="1424" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">deposit</text></switch></g><path d="M 6120 5840 Q 6300 5912 6480 5840 Q 6660 5768 6840 5840 L 6840 6040 Q 6660 5968 6480 6040 Q 6300 6112 6120 6040 L 6120 5840 Z" fill="#fff2cc" stroke="#d6b656" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 178px; height: 1px; padding-top: 1485px; margin-left: 1531px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">deposit</div></div></div></foreignObject><text x="1620" y="1494" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">deposit</text></switch></g><rect x="4980" y="5660" width="1000" height="440" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 1470px; margin-left: 1493px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 21px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-weight: bold; white-space: nowrap;">Deposits get included<br />the first L2 block that<br />adopts the L1 origin the<br />deposits were made in.</div></div></div></foreignObject><text x="1493" y="1476" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="21px" text-anchor="end" font-weight="bold">Deposits get included...</text></switch></g><rect x="20" y="2300" width="2560" height="640" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 655px; margin-left: 7px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Security types on L2:<br />- "unsafe": not submitted on L1<br />- "safe": is confirmed on L1<br />- "finalized": fully derived from finalized L1 data</div></div></div></foreignObject><text x="7" y="664" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px">Security types on L2:...</text></switch></g><rect x="60" y="3140" width="2000" height="640" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 865px; margin-left: 17px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Security types on L1:<br />- "unsafe": very new<br />- "safe": decent attestation ratio<br />- "finalized": with FFG finality gadget</div></div></div></foreignObject><text x="17" y="874" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px">Security types on L1:...</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="11984px" height="4564px" viewBox="-0.5 -0.5 11984 4564"><defs/><g><path d="M 4820 2900 L 5820 2900 L 5900 3000 L 5820 3100 L 4820 3100 L 4900 3000 Z" fill="#99ffcc" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 772px; margin-left: 1206px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="1338" y="772" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 6900 2900 L 7900 2900 L 7980 3000 L 7900 3100 L 6900 3100 L 6980 3000 Z" fill="#a8fff6" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 772px; margin-left: 1726px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="1858" y="772" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 5860 2900 L 6860 2900 L 6940 3000 L 6860 3100 L 5860 3100 L 5940 3000 Z" fill="#96ffe3" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 772px; margin-left: 1466px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="1598" y="772" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 4100 3000 L 4900 3000" fill="none" stroke="rgb(0, 0, 0)" stroke-width="28" stroke-miterlimit="10" stroke-dasharray="84 84" pointer-events="stroke"/><path d="M 3780 2900 L 4020 2900 L 4100 3000 L 4020 3100 L 3780 3100 L 3860 3000 Z" fill="#99ff99" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 74px; height: 1px; padding-top: 772px; margin-left: 946px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="983" y="772" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">100</text></switch></g><rect x="5860" y="1340" width="1000" height="560" fill="#96ffe3" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 1466px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Batch Queue</div></div></div></foreignObject><text x="1590" y="414" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">Batch Queue</text></switch></g><rect x="7940" y="1340" width="1000" height="560" fill="#9ceeff" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 1986px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Engine Queue</div></div></div></foreignObject><text x="2110" y="414" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">Engine Queue</text></switch></g><rect x="6900" y="1340" width="1000" height="560" fill="#a8fff6" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 1726px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>PayloadAttributes</div><div>Queue<br /></div></div></div></div></foreignObject><text x="1850" y="414" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">PayloadAttributes...</text></switch></g><rect x="4820" y="1340" width="1000" height="560" fill="#99ffcc" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 1206px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>Channel</div><div>Input-reader<br /></div></div></div></div></foreignObject><text x="1330" y="414" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">Channel...</text></switch></g><rect x="3780" y="1340" width="1000" height="560" fill="#99ff99" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 946px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;"><div>Channel</div><div>Bank<br /></div></div></div></div></foreignObject><text x="1070" y="414" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">Channel...</text></switch></g><rect x="1700" y="1340" width="1000" height="560" fill="#e3ff96" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 426px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">L1 Traversal</div></div></div></foreignObject><text x="550" y="414" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">L1 Traversal</text></switch></g><path d="M 1700 2900 L 2700 2900 L 2780 3000 L 2700 3100 L 1700 3100 L 1780 3000 Z" fill="#e3ff96" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 772px; margin-left: 426px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="558" y="772" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">100</text></switch></g><path d="M 8340 3000 L 8980 3000" fill="none" stroke="rgb(0, 0, 0)" stroke-width="28" stroke-miterlimit="10" stroke-dasharray="84 84" pointer-events="stroke"/><path d="M 7940 2900 L 8260 2900 L 8340 3000 L 8260 3100 L 7940 3100 L 8020 3000 Z" fill="#9ceeff" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 94px; height: 1px; padding-top: 772px; margin-left: 1986px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="2033" y="772" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 7120 540 C 6912 540 6860 700 7026.4 732 C 6860 802.4 7047.2 956 7182.4 892 C 7276 1020 7588 1020 7692 892 C 7900 892 7900 764 7770 700 C 7900 572 7692 444 7510 508 C 7380 412 7172 412 7120 540 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 258px; height: 1px; padding-top: 175px; margin-left: 1716px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">L1 Deposits</div></div></div></foreignObject><text x="1845" y="184" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">L1 Deposits</text></switch></g><path d="M 8660 1980 L 8940 1980 L 9020 2080 L 8940 2180 L 8660 2180 L 8740 2080 Z" fill="#9ceeff" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 84px; height: 1px; padding-top: 542px; margin-left: 2166px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="2208" y="542" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 5860 2460 L 6900 2460 L 6980 2560 L 6900 2660 L 5860 2660 L 5940 2560 Z" fill="#96ffe3" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 274px; height: 1px; padding-top: 662px; margin-left: 1466px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="1603" y="662" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 4820 2460 L 5820 2460 L 5900 2560 L 5820 2660 L 4820 2660 L 4900 2560 Z" fill="#99ffcc" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 662px; margin-left: 1206px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="1338" y="662" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 4540 2460 L 4780 2460 L 4860 2560 L 4780 2660 L 4540 2660 L 4620 2560 Z" fill="#99ff99" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 74px; height: 1px; padding-top: 662px; margin-left: 1136px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="1173" y="662" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 1700 2660 L 2700 2660 L 2780 2760 L 2700 2860 L 1700 2860 L 1780 2760 Z" fill="#e3ff96" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 712px; margin-left: 426px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="558" y="712" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">100</text></switch></g><path d="M 3780 2660 L 4020 2660 L 4100 2760 L 4020 2860 L 3780 2860 L 3860 2760 Z" fill="#99ff99" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 74px; height: 1px; padding-top: 712px; margin-left: 946px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="983" y="712" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">100</text></switch></g><path d="M 4820 3300 L 5820 3300 L 5900 3400 L 5820 3500 L 4820 3500 L 4900 3400 Z" fill="#99ffcc" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 1206px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="1338" y="872" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 6900 3300 L 7900 3300 L 7980 3400 L 7900 3500 L 6900 3500 L 6980 3400 Z" fill="#a8fff6" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 1726px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="1858" y="872" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 5860 3300 L 6860 3300 L 6940 3400 L 6860 3500 L 5860 3500 L 5940 3400 Z" fill="#96ffe3" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 1466px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="1598" y="872" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 3780 3300 L 4780 3300 L 4860 3400 L 4780 3500 L 3780 3500 L 3860 3400 Z" fill="#99ff99" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 946px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="1078" y="872" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 1700 3300 L 2700 3300 L 2780 3400 L 2700 3500 L 1700 3500 L 1780 3400 Z" fill="#e3ff96" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 426px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="558" y="872" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 7940 3300 L 8940 3300 L 9020 3400 L 8940 3500 L 7940 3500 L 8020 3400 Z" fill="#9ceeff" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 1986px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="2118" y="872" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><rect x="9720" y="1152" width="2160" height="520" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 353px; margin-left: 2432px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 50px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">1) find safe L2 block<br />with canonical L1 origin</div></div></div></foreignObject><text x="2432" y="368" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="50px">1) find safe L2 block...</text></switch></g><rect x="9720" y="2472" width="2240" height="520" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 683px; margin-left: 2432px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 50px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">3) reset all stage origins,<br />traverse chain back</div></div></div></foreignObject><text x="2432" y="698" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="50px">3) reset all stage orig...</text></switch></g><rect x="9720" y="3112" width="1880" height="520" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 843px; margin-left: 2432px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 50px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">4) dry-run pipeline<br />to heal stage buffers</div></div></div></foreignObject><text x="2432" y="858" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="50px">4) dry-run pipeline...</text></switch></g><rect x="9720" y="3752" width="2120" height="520" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 1003px; margin-left: 2432px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 50px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">5) new L1 data<br />can now stream into L2</div></div></div></foreignObject><text x="2432" y="1018" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="50px">5) new L1 data...</text></switch></g><rect x="9720" y="1832" width="2160" height="520" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 523px; margin-left: 2432px;"><div style="box-sizing: border-box; font-size: 0px; text-align: left;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 50px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">2) Stages with gaps will<br /> reconstruct buffer data</div></div></div></foreignObject><text x="2432" y="538" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="50px">2) Stages with gaps wi...</text></switch></g><path d="M 2055.29 1022 L 2304.71 1022 L 2304.71 1116.35 L 2600.82 1116.35 L 2180 1258 L 1759.18 1116.35 L 2055.29 1116.35 Z" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/><path d="M 8609.69 1258 L 8360.28 1258 L 8360.28 1163.65 L 8064.16 1163.65 L 8484.99 1022 L 8905.81 1163.65 L 8609.69 1163.65 Z" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/><rect x="460" y="4140" width="1160" height="400" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 1085px; margin-left: 260px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 26px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-style: italic; white-space: nowrap;">Numbers for illustration,<br /> referring to L1 origin<br />block numbers</div></div></div></foreignObject><text x="260" y="1093" fill="#000000" font-family="Helvetica" font-size="26px" text-anchor="middle" font-style="italic">Numbers for illustrati...</text></switch></g><rect x="60" y="1900" width="1360" height="600" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 550px; margin-left: 185px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 40px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">"<b>ResetStep</b>":<br style="font-size: 40px" />reset stage with<br style="font-size: 40px" />distance from next</div></div></div></foreignObject><text x="185" y="562" fill="#000000" font-family="Helvetica" font-size="40px" text-anchor="middle">"ResetStep":...</text></switch></g><rect x="20" y="2940" width="1440" height="1000" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 860px; margin-left: 185px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 40px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">"<b>Step</b>":<br style="font-size: 40px" />progress pipeline.<br />Start closest to L2,<br />visit previous stage<br />for more input data.</div></div></div></foreignObject><text x="185" y="872" fill="#000000" font-family="Helvetica" font-size="40px" text-anchor="middle">"Step":...</text></switch></g><rect x="1760" y="3860" width="7080" height="240" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 995px; margin-left: 1325px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 36px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">L1 block hash &gt; Data TXs &gt; Channel Frames &gt; Batches &gt; Ordered batches &gt; PayloadAttributes &gt; L2 payloads</div></div></div></foreignObject><text x="1325" y="1006" fill="#000000" font-family="Helvetica" font-size="36px" text-anchor="middle">L1 block hash &gt; Data TXs &gt; Channel Frames &gt; Batches &gt; Ordered batches &gt; PayloadAttributes &gt; L2 payl...</text></switch></g><rect x="3800" y="2100" width="680" height="560" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 595px; margin-left: 1118px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 36px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-style: italic; white-space: nowrap;">Resets<br /><b>Channel</b><br /><b>timeout</b></div></div></div></foreignObject><text x="1118" y="606" fill="#000000" font-family="Helvetica" font-size="36px" text-anchor="end" font-style="italic">Resets...</text></switch></g><rect x="7620" y="1900" width="920" height="560" fill="none" stroke="none" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 545px; margin-left: 2133px;"><div style="box-sizing: border-box; font-size: 0px; text-align: right;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 36px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; font-style: italic; white-space: nowrap;"><div>Resets</div><b>Sequencing</b><br /><b>window</b></div></div></div></foreignObject><text x="2133" y="556" fill="#000000" font-family="Helvetica" font-size="36px" text-anchor="end" font-style="italic">ResetsSequenc...</text></switch></g><rect x="2740" y="1340" width="1000" height="560" fill="#c9f783" stroke="#000000" stroke-width="4" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 248px; height: 1px; padding-top: 405px; margin-left: 686px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">L1 Retrieval</div></div></div></foreignObject><text x="810" y="414" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">L1 Retrieval</text></switch></g><path d="M 2740 2900 L 3740 2900 L 3820 3000 L 3740 3100 L 2740 3100 L 2820 3000 Z" fill="#c9f783" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 772px; margin-left: 686px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="818" y="772" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">100</text></switch></g><path d="M 2740 2660 L 3740 2660 L 3820 2760 L 3740 2860 L 2740 2860 L 2820 2760 Z" fill="#c9f783" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 712px; margin-left: 686px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">100</div></div></div></foreignObject><text x="818" y="712" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">100</text></switch></g><path d="M 2740 3300 L 3740 3300 L 3820 3400 L 3740 3500 L 2740 3500 L 2820 3400 Z" fill="#c9f783" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 264px; height: 1px; padding-top: 872px; margin-left: 686px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">130</div></div></div></foreignObject><text x="818" y="872" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">130</text></switch></g><path d="M 3152.45 1022 L 3401.87 1022 L 3401.87 1116.35 L 3697.98 1116.35 L 3277.16 1258 L 2856.34 1116.35 L 3152.45 1116.35 Z" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/><path d="M 7295.29 1062 L 7544.71 1062 L 7544.71 1156.35 L 7840.82 1156.35 L 7420 1298 L 6999.18 1156.35 L 7295.29 1156.35 Z" fill="#000000" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-linejoin="round" stroke-miterlimit="10" pointer-events="all"/><path d="M 3020 500 C 2812 500 2760 660 2926.4 692 C 2760 762.4 2947.2 916 3082.4 852 C 3176 980 3488 980 3592 852 C 3800 852 3800 724 3670 660 C 3800 532 3592 404 3410 468 C 3280 372 3072 372 3020 500 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 258px; height: 1px; padding-top: 165px; margin-left: 691px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">L1 Data</div></div></div></foreignObject><text x="820" y="174" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">L1 Data</text></switch></g><path d="M 1940 500 C 1732 500 1680 660 1846.4 692 C 1680 762.4 1867.2 916 2002.4 852 C 2096 980 2408 980 2512 852 C 2720 852 2720 724 2590 660 C 2720 532 2512 404 2330 468 C 2200 372 1992 372 1940 500 Z" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 258px; height: 1px; padding-top: 165px; margin-left: 421px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">L1 Chain</div></div></div></foreignObject><text x="550" y="174" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">L1 Chain</text></switch></g><rect x="8220" y="220" width="520" height="520" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-width="12" pointer-events="none"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 128px; height: 1px; padding-top: 120px; margin-left: 2056px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">L2 Exec<br style="font-size: 30px;" />Engine</div></div></div></foreignObject><text x="2120" y="129" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="30px" text-anchor="middle">L2 Exec...</text></switch></g><rect x="8020" y="220" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8100" y="300" width="80" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8020" y="380" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8100" y="460" width="80" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8020" y="540" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8100" y="620" width="80" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8020" y="700" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="220" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="300" width="80" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="380" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="460" width="80" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="540" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="620" width="80" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8780" y="700" width="160" height="40" fill="#000000" stroke="none" pointer-events="none"/><rect x="8300" y="780" width="40" height="80" fill="#000000" stroke="none" pointer-events="none"/><rect x="8220" y="780" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8460" y="780" width="40" height="80" fill="#000000" stroke="none" pointer-events="none"/><rect x="8380" y="780" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8620" y="780" width="40" height="80" fill="#000000" stroke="none" pointer-events="none"/><rect x="8540" y="780" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8700" y="780" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8300" y="100" width="40" height="80" fill="#000000" stroke="none" pointer-events="none"/><rect x="8220" y="20" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8460" y="100" width="40" height="80" fill="#000000" stroke="none" pointer-events="none"/><rect x="8380" y="20" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8620" y="100" width="40" height="80" fill="#000000" stroke="none" pointer-events="none"/><rect x="8540" y="20" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><rect x="8700" y="20" width="40" height="160" fill="#000000" stroke="none" pointer-events="none"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 233px; margin-left: 2535px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: rgb(0, 0, 0); "><div style="display: inline-block; font-size: 70px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: nowrap;">Reset:</div></div></div></foreignObject><text x="2535" y="254" fill="rgb(0, 0, 0)" font-family="Helvetica" font-size="70px" text-anchor="middle">Reset:</text></switch></g><path d="M 6940 2460 L 7900 2460 L 7980 2560 L 7900 2660 L 6940 2660 L 7020 2560 Z" fill="#a8fff6" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 254px; height: 1px; padding-top: 662px; margin-left: 1736px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;"><div>110</div></div></div></div></foreignObject><text x="1863" y="662" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g><path d="M 7940 2460 L 8260 2460 L 8340 2560 L 8260 2660 L 7940 2660 L 8020 2560 Z" fill="#9ceeff" stroke="#000000" stroke-width="4" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(-0.5 -0.5)scale(4)"><switch><foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 94px; height: 1px; padding-top: 662px; margin-left: 1986px;"><div style="box-sizing: border-box; font-size: 0px; text-align: center;" data-drawio-colors="color: #000000; "><div style="display: inline-block; font-size: 30px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: none; white-space: normal; overflow-wrap: normal;">110</div></div></div></foreignObject><text x="2033" y="662" fill="#000000" font-family="Helvetica" font-size="30px" text-anchor="middle">110</text></switch></g></g><switch><g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"/><a transform="translate(0,-5)" xlink:href="https://www.diagrams.net/doc/faq/svg-export-text-problems" target="_blank"><text text-anchor="middle" font-size="10px" x="50%" y="100%">Text is not SVG - cannot display</text></a></switch></svg>
\ No newline at end of file
...@@ -4,9 +4,8 @@ ...@@ -4,9 +4,8 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Standard Bridges](#standard-bridges) - [Token Depositing](#token-depositing)
- [Token Depositing](#token-depositing) - [Upgradability](#upgradability)
- [Upgradability](#upgradability)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -22,22 +22,21 @@ with the authorization and validation conditions on L2. ...@@ -22,22 +22,21 @@ with the authorization and validation conditions on L2.
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Deposits](#deposits) - [The Deposited Transaction Type](#the-deposited-transaction-type)
- [The Deposited Transaction Type](#the-deposited-transaction-type) - [Source hash computation](#source-hash-computation)
- [Source hash computation](#source-hash-computation) - [Kinds of Deposited Transactions](#kinds-of-deposited-transactions)
- [Kinds of Deposited Transactions](#kinds-of-deposited-transactions) - [Validation and Authorization of Deposited Transactions](#validation-and-authorization-of-deposited-transactions)
- [Validation and Authorization of Deposited Transactions](#validation-and-authorization-of-deposited-transactions) - [Execution](#execution)
- [Execution](#execution) - [Nonce Handling](#nonce-handling)
- [Nonce Handling](#nonce-handling) - [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction)
- [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) - [Special Accounts on L2](#special-accounts-on-l2)
- [Special Accounts on L2](#special-accounts-on-l2) - [L1 Attributes Depositor Account](#l1-attributes-depositor-account)
- [L1 Attributes Depositor Account](#l1-attributes-depositor-account) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract)
- [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - [L1 Attributes Predeployed Contract: Reference Implementation](#l1-attributes-predeployed-contract-reference-implementation)
- [L1 Attributes Predeployed Contract: Reference Implementation](#l1-attributes-predeployed-contract-reference-implementation) - [User-Deposited Transactions](#user-deposited-transactions)
- [User-Deposited Transactions](#user-deposited-transactions) - [Deposit Contract](#deposit-contract)
- [Deposit Contract](#deposit-contract) - [Address Aliasing](#address-aliasing)
- [Address Aliasing](#address-aliasing) - [Deposit Feed Contract: Reference Implementation](#deposit-feed-contract-reference-implementation)
- [Deposit Feed Contract: Reference Implementation](#deposit-feed-contract-reference-implementation)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
# L2 Chain Derivation Specification
<!-- All glossary references in this file. -->
[g-derivation]: glossary.md#L2-chain-derivation
[g-payload-attr]: glossary.md#payload-attributes
[g-block]: glossary.md#block
[g-exec-engine]: glossary.md#execution-engine
[g-reorg]: glossary.md#re-organization
[g-receipts]: glossary.md#receipt
[g-inception]: glossary.md#L2-chain-inception
[g-deposit-contract]: glossary.md#deposit-contract
[g-deposited]: glossary.md#deposited-transaction
[g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction
[g-user-deposited]: glossary.md#user-deposited-transaction
[g-deposits]: glossary.md#deposits
[g-deposit-contract]: glossary.md#deposit-contract
[g-l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract
[g-depositing-call]: glossary.md#depositing-call
[g-depositing-transaction]: glossary.md#depositing-transaction
[g-sequencing]: glossary.md#sequencing
[g-sequencer]: glossary.md#sequencer
[g-sequencing-epoch]: glossary.md#sequencing-epoch
[g-sequencing-window]: glossary.md#sequencing-window
[g-sequencer-batch]: glossary.md#sequencer-batch
[g-l2-genesis]: glossary.md#l2-genesis-block
[g-l2-chain-inception]: glossary.md#L2-chain-inception
[g-batcher-transaction]: glossary.md#batcher-transaction
[g-avail-provider]: glossary.md#data-availability-provider
[g-batcher]: glossary.md#batcher
[g-l2-output]: glossary.md#l2-output
[g-fault-proof]: glosary.md#fault-proof
[g-channel]: glossary.md#channel
[g-channel-frame]: glossary.md#channel-frame
[g-rollup-node]: glossary.md#rollup-node
[g-channel-timeout]: glossary.md#channel-timeout
[g-block-time]: glossary.md#block-time
[g-time-slot]: glossary.md#time-slot
[g-consolidation]: glossary.md#unsafe-block-consolidation
[g-safe-l2-head]: glossary.md#safe-l2-head
[g-unsafe-l2-head]: glossary.md#unsafe-l2-head
[g-unsafe-l2-block]: glossary.md#unsafe-l2-block
[g-unsafe-sync]: glossary.md#unsafe-sync
[g-l1-origin]: glossary.md#l1-origin
[g-deposit-tx-type]: glossary.md#deposited-transaction-type
[g-finalized-l2-head]: glossary.md#finalized-l2-head
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
- [Overview](#overview)
- [Eager Block Derivation](#eager-block-derivation)
- [Batch Submission](#batch-submission)
- [Sequencing & Batch Submission Overview](#sequencing--batch-submission-overview)
- [Batch Submission Wire Format](#batch-submission-wire-format)
- [Batcher Transaction Format](#batcher-transaction-format)
- [Frame Format](#frame-format)
- [Channel Format](#channel-format)
- [Batch Format](#batch-format)
- [Architecture](#architecture)
- [L2 Chain Derivation Pipeline](#l2-chain-derivation-pipeline)
- [L1 Traversal](#l1-traversal)
- [L1 Retrieval](#l1-retrieval)
- [Channel Bank](#channel-bank)
- [Batch Decoding](#batch-decoding)
- [Batch Buffering](#batch-buffering)
- [Payload Attributes Derivation](#payload-attributes-derivation)
- [Engine Queue](#engine-queue)
- [Resetting the Pipeline](#resetting-the-pipeline)
- [Deriving Payload Attributes](#deriving-payload-attributes)
- [Deriving the Transaction List](#deriving-the-transaction-list)
- [Building Individual Payload Attributes](#building-individual-payload-attributes)
- [WARNING: BELOW THIS LINE, THE SPEC HAS NOT BEEN REVIEWED AND MAY CONTAIN MISTAKES](#warning-below-this-line-the-spec-has-not-been-reviewed-and-may-contain-mistakes)
- [Communication with the Execution Engine](#communication-with-the-execution-engine)
- [Handling L1 Re-Orgs](#handling-l1-re-orgs)
- [Resetting the Engine Queue](#resetting-the-engine-queue)
- [Resetting Payload Attribute Derivation](#resetting-payload-attribute-derivation)
- [Resetting Batch Decoding](#resetting-batch-decoding)
- [Resetting Channel Buffering](#resetting-channel-buffering)
- [Resetting L1 Retrieval & L1 Traversal](#resetting-l1-retrieval--l1-traversal)
- [Reorgs Post-Merge](#reorgs-post-merge)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
# Overview
> **Note**: the following assumes a single sequencer and batcher. In the future, the design might be adapted to
> accomodate multiple such entities.
[L2 chain derivation][g-derivation] — deriving L2 [blocks][g-block] from L1 data — is one of the main responsability of
the [rollup node][g-rollup-node], both in validator mode, and in sequencer mode (where derivation acts as a sanity check
on sequencing, and enables detecting L1 chain [re-organizations][g-reorg]).
The L2 chain is derived from the L1 chain. In particular, each L1 block is mapped to an L2 [sequencing
epoch][g-sequencing-epoch] comprising multiple L2 blocks. The epoch number is defined to be equal to the corresponding
L1 block number.
To derive the L2 blocks in an epoch `E`, we need the following inputs:
- The L1 [sequencing window][g-sequencing-window] for epoch `E`: the L1 blocks in the range `[E, E + SWS)` where `SWS`
is the sequencing window size (note that this means that epochs are overlapping). In particular we need:
- The [batcher transactions][g-batcher-transactions] included in the sequencing window. These allow us to
reconstruct [sequencer batches][g-sequencer-batch] containing the transactions to include in L2 blocks (each batch
maps to a single L2 block).
- The [deposits][g-deposits] made in L1 block `E` (in the form of events emitted by the [deposit
contract][g-deposit-contract]).
- The L1 block attributes from L1 block `E` (to derive the [L1 attributes deposited transaction][g-l1-attr-deposit]).
- The state of the L2 chain after the last L2 block of epoch `E - 1`, or — if epoch `E - 1` does not exist — the
[genesis state][g-l2-genesis] (cf. TODO) of the L2 chain.
- An epoch `E` does not exist if `E <= L2CI`, where `L2CI` is the [L2 chain inception][g-l2-chain-inception].
> **TODO** specify sequencing window size
> **TODO** specify genesis block / state (in its own document? include/link predeploy.md)
To derive the whole L2 chain from scratch, we simply start with the [L2 genesis state][g-l2-genesis], and the [L2 chain
inception][g-l2-chain-inception] as first epoch, then process all sequencing windows in order. Refer to the
[Architecture section][architecture] for more information on how we implement this in practice.
Each epoch may contain a variable number of L2 blocks (one every `l2_block_time`, 2s on Optimism), at the discretion of
[the sequencer][g-sequencer], but subject to the following constraints for each block:
- `min_l2_timestamp <= block.timestamp < max_l2_timestamp`, where
- all these values are denominated in seconds
- `min_l2_timestamp = prev_l2_timestamp + l2_block_time`
- `prev_l2_timestamp` is the timestamp of the previous L2 block
- `l2_block_time` is a configurable parameter of the time between L2 blocks (on Optimism, 2s)
- `max_l2_timestamp = max(l1_timestamp + max_sequencer_drift, min_l2_timestamp + l2_block_time)`
- `l1_timestamp` is the timestamp of the L1 block associated with the L2 block's epoch
- `max_sequencer_drift` is the most a sequencer is allowed to get ahead of L1
> **TODO** specify max sequencer drift
Put together, these constraints mean that there must be an L2 block every `l2_block_time` seconds, and that the
timestamp for the first L2 block of an epoch must never fall behind the timestamp of the L1 block matching the epoch.
Post-merge, Ethereum has a fixed [block time][g-block-time] of 12s (though some slots can be skipped). It is thus
expected that, most of the time, each epoch on Optimism will contain `12/2 = 6` L2 blocks. The sequencer can however
lengthen or shorten epochs (subject to above constraints). The rationale is to maintain liveness in case of either a
skipped slot on L1, or a temporary loss of connection to L1 — which requires longer epochs. Shorter epochs are then
required to avoid L2 timestamps drifting further and further ahead of L1.
## Eager Block Derivation
In practice, it is often not necesary to wait for a full sequencing window of L1 blocks in order to start deriving the
L2 blocks in an epoch. Indeed, as long as we are able to reconstruct sequential batches, we can start deriving the
corresponding L2 blocks. We call this *eager block derivation*.
However, in the very worst case, we can only reconstruct the batch for the first L2 block in the epoch by reading the
last L1 block of the sequencing window. This happens when some data for that batch is included in the last L1 block of
the window. In that case, not only can we not derive the first L2 block in the poch, we also can't derive any further L2
block in the epoch until then, as they need the state that results from applying the epoch's first L2 block. (Note that
this only applies to *block* derivation. We can still derive further batches, we just won't be able to create blocks
from them.)
------------------------------------------------------------------------------------------------------------------------
# Batch Submission
## Sequencing & Batch Submission Overview
The [sequencer][g-sequencer] accepts L2 transactions from users. It is responsible for building blocks out of these. For
each such block, it also creates a corresponding [sequencer batch][g-sequencer-batch]. It is also responsible for
submitting each batch to a [data availability provider][g-avail-provider] (e.g. Ethereum calldata), which it does via
its [batcher][g-batcher] component.
The difference between an L2 block and a batch is subtle but important: the block includes an L2 state root, whereas the
batch only commits to transactions at a given L2 timestamp (equivalently: L2 block number). A block also includes a
reference to the previous block (\*).
(\*) This matters in some edge case where a L1 reorg would occur and a batch would be reposted to the L1 chain but not
the preceding batch, whereas the predecessor of an L2 block cannot possibly change.
This means that even if the sequencer applies a state transition incorrectly, the transactions in the batch will stil be
considered part of the canonical L2 chain. Batches are still subject to validity checks (i.e. they have to be encoded
correctly), and so are individual transactions within the batch (e.g. signatures have to be valid). Invalid batches and
invalid individual transactions within an otherwise valid batch are discarded by correct nodes.
If the sequencer applies a state transition incorrectly and posts an [output root][g-l2-output], then this output root
will be incorrect. The incorrect output root which will be challenged by a [fault proof][g-fault-proof], then replaced
by a correct output root **for the existing sequencer batches.**
Refer to the [Batch Submission specification][batcher-spec] for more information.
[batcher-spec]: batching.md
> **TODO** rewrite the batch submission specification
>
> Here are some things that should be included there:
>
> - There may be different concurrent data submissions to L1
> - There may be different actors that submit the data, the system cannot rely on a single EOA nonce value.
> - The batcher requests safe L2 safe head from the rollup node, then queries the execution engine for the block data.
> - In the future we might be able to get the safe hea dinformation from the execution engine directly. Not possible
> right now but there is an upstream geth PR open.
## Batch Submission Wire Format
[wire-format]: #batch-submission-wire-format
Batch submission is closely tied to L2 chain derivation because the derivation process must decode the batches that have
been encoded for the purpose of batch submission.
The [batcher][g-batcher] submits [batcher transactions][g-batcher-transaction] to a [data availability
provider][g-avail-provider]. These transactions contain one or multiple [channel frames][g-channel-frame], which are
chunks of data belonging to a [channel][g-channel].
A [channel][g-channel] is a sequence of [sequencer batches][g-sequencer-batch] (for sequential blocks) compressed
together. The reason to group multiple batches together is simply to obtain a better compression rate, hence reducing
data availability costs.
Channels might be too large to fit in a single [batcher transaction][g-batcher-transaction], hence we need to split it
into chunks known as [channel frames][g-channel-frame]. A single batcher transaction can also carry multiple frames
(belonging to the same or to different channels).
This design gives use the maximum flexibility in how we aggregate batches into channels, and split channels over batcher
transactions. It notably allows us to maximize data utilisation in a batcher transaction: for instance it allows us to
pack the final (small) frame of a window with large frames from the next window. It also allows the [batcher][g-batcher]
to employ multiple signers (private keys) to submit one or multiple channels in parallel (1).
(1) This helps alleviate issues where, because of transaction nonces, multiple transactions made by the same signer are
stuck waiting on the inclusion of a previous transaction.
Also note that we use a streaming compression scheme, and we do not need to know how many blocks a channel will end up
containing when we start a channel, or even as we send the first frames in the channel.
All of this is illustrated in the following diagram.
> **TODO** improve diagram
>
> - I'm a fan of the 4 lines "Transactions" to "L2 Blocks"
> - albeit it would good to show that channels & frames can occur out of order
> - but maybe that makes the diagram too hard to read and we can just include a comment afterwards saying that in
> general, reordering is possible (maybe show a second diagram showcasing a simple reordering?
> - I think L1 blocks should be a new line above "Transactions" — also show deposits (w/ a number) for each block
> - We shouldn't use the L1 attributes tx as a separate line, it makes it look like a additional layer of "data
> derivation", which it is not. Instead I would tag each L2 block with its epoch number.
> - Include numbered deposits under L2 blocks
> - Let's use a sequencing window of size 2 to keep the diagram small
> - Include a textual explanation of the diagram below it
![batch derivation chain diagram](./assets/batch-deriv-chain.svg)
### Batcher Transaction Format
Batcher transactions are encoded as `version_byte ++ rollup_payload` (where `++` denotes concatenation).
| `version_byte` | `rollup_payload` |
|----------------|------------------------------------------------|
| 0 | `frame ...` (one or more frames, concatenated) |
Unknown versions make the batcher transaction invalid (it must be ignored by the rollup node).
The `rollup_payload` may be right-padded with 0s, which will be ignored. It's allowed for them to be
interpreted as frames for channel 0, which must always be ignored.
> **TODO** specify batcher authentication (i.e. where do we store / make available the public keys of authorize batcher
> signers)
### Frame Format
A [channel frame][g-channel-frame] is encoded as:
```text
frame = channel_id ++ frame_number ++ frame_data_length ++ frame_data ++ is_last
channel_id = random ++ timestamp
random = bytes32
timestamp = uvarint
frame_number = uvarint
frame_data_length = uvarint
frame_data = bytes
is_last = bool
```
> **TODO** replace `uvarint` by fixed size integers
where:
- `uvarint` is a variable-length encoding of a 64-bit unsigned integer into between 1 and 9 bytes, [as specified in
SQLite 4][sqlite-uvarint].
- `channel_id` uniquely identifies a channel as the concatenation of a random value and a timestamp
- `random` is a random value such that two channels with different batches should have a different random value
- `timestamp` is the time at which the channel was created (UNIX time in seconds)
- The ID includes both the random value and the timestamp, in order to prevent a malicious sequencer from reusing
the random value after the channel has [timed out][g-channel-timeout] (refer to the [batcher
specification][batcher-spec] to learn more about channel timeouts). This will also allow us substitute `random` by
a hash commitment to the batches, should we want to do so in the future.
- Channels whose timestamp are higher than that of the L1 block they first appear in must be ignored. Note that L1
nodes have a soft constraint to ignore blocks whose timestamps that are ahead of the wallclock time by a certain
margin. (A soft constraint is not a consensus rule — nodes will accept such blocks in the canonical chain but will
not attempt to build directly on them.)
- `frame_number` identifies the index of the frame within the channel
- `frame_data_length` is the length of `frame_data` in bytes
- `frame_data` is a sequence of bytes belonging to the channel, logically after the bytes from the previous frames
- `is_last` is a single byte with a value of 1 if the frame is the last in the channel, 0 if there are frames in the
channel. Any other value makes the frame invalid (it must be ignored by the rollup node).
> **TODO**
>
> - Is that requirement to drop channels correct?
> - Is it implemented as such?
> - Do we drop the channel or just the first frame? End result is the same but this changes the channel bank size, which
> can influence things down the line!!
[sqlite-uvarint]: https://www.sqlite.org/src4/doc/trunk/www/varint.wiki
[batcher-spec]: batching.md
### Channel Format
A channel is encoded as `channel_encoding`, defined as:
```text
rlp_batches = []
for batch in batches:
rlp_batches.append(batch)
channel_encoding = compress(rlp_batches)
```
where:
- `batches` is the input, a sequence of batches byte-encoded as per the next section ("Batch Encoding")
- `rlp_batches` is the concatenation of the RLP-encoded batches
- `compress` is a function performing compression, using the ZLIB algorithm (as specified in [RFC-1950][rfc1950]) with
no dictionary
- `channel_encoding` is the compressed version of `rlp_batches`
[rfc1950]: https://www.rfc-editor.org/rfc/rfc1950.html
When decompressing a channel, we limit the amount of decompressed data to `MAX_RLP_BYTES_PER_CHANNEL`, in order to avoid
"zip-bomb" types of attack (where a small compressed input decompresses to a humongous amount of data). If the
decompressed data exceeds the limit, things proceeds as thought the channel contained only the first
`MAX_RLP_BYTES_PER_CHANNEL` decompressed bytes.
> **TODO** specify `MAX_RLP_BYTES_PER_CHANNEL`
While the above pseudocode implies that all batches are known in advance, it is possible to perform streaming
compression and decompression of RLP-encoded batches. This means it is possible to start including channel frames in a
[batcher transaction][g-batcher-transaction] before we know how many batches (and how many frames) the channel will
contain.
### Batch Format
[batch-format]: #batch-format
Recall that a batch contains a list of transactions to be included in a specific L2 block.
A batch is encoded as `batch_version ++ content`, where `content` depends on the version:
| `batch_version` | `content` |
| --------------- | --------------------------------------------------------------------- |
| 0 | `rlp_encode([epoch_number, epoch_hash, timestamp, transaction_list])` |
where:
- `rlp_encode` is a function that encodes a batch according to the [RLP format], and `[x, y, z]` denotes a list
containing items `x`, `y` and `z`
- `epoch_number` and `epoch_hash` are the number and hash of the L1 block corresponding to the [sequencing
epoch][g-sequencing-epoch] of the L2 block
- `timestamp` is the timestamp of the L2 block
- `transaction_list` is an RLP-encoded list of [EIP-2718] encoded transactions.
[RLP format]: https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp/
[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718
Unknown versions make the batch invalid (it must be ignored by the rollup node), as do malformed contents.
The `epoch_number` and the `timestamp` must also respect the constraints listed in the [Batch
Buffering][batch-buffering] section, otherwise the batch is considered invalid.
------------------------------------------------------------------------------------------------------------------------
# Architecture
[architecture]: #architecture
The above describes the general process of L2 chain derivation, and specifies how batches are encoded within [batcher
transactions][g-batcher-transaction].
However, there remains many details to specify. These are mostly tied to the rollup node architecture for derivation.
Therefore we present this architecture as a way to specify these details.
A validator that only reads from L1 (and so doesn't interact with the sequencer directly) does not need to be
implemented in the way presented below. It does however need to derive the same blocks (i.e. it needs to be semantically
equivalent). We do believe the architecture presented below has many advantages.
## L2 Chain Derivation Pipeline
[pipeline]: #l2-chain-derivation-pipeline
Our architecture decomposes the derivation process into a pipeline made up of the following stages:
1. L1 Traversal
2. L1 Retrieval
3. Channel Bank
4. Batch Decoding (called `ChannelInReader` in the code)
5. Batch Buffering (Called `BatchQueue` in the code)
6. Payload Attributes Derivation (called `AttributesQueue` in the code)
7. Engine Queue
> **TODO** can we change code names for these three things? maybe as part of a refactor
The data flows flows from the start (outer) of the pipeline towards the end (inner). Each stage is able to push data to
the next stage.
However, data is *processed* in reverse order. Meaning that if there is any data to be processed in the last stage, it
will be processed first. Processing proceeds in "steps" that can be taken at each stage. We try to take as many steps as
possible in the last (most inner) stage before taking any steps in its outer stage, etc.
This ensures that we use the data we already have before pulling more data and minimizes the latency of data traversing
the derivation pipeline.
Each stage can maintain its own inner state as necessary. **In particular, each stage maintains a L1 block reference
(number + hash) to the latest L1 block such that all data originating from previous blocks has been processed, and the
data from that block is or has been processed.**
Let's briefly describe each stage of the pipeline.
### L1 Traversal
In the *L1 Traversal* stage, we simply read the header of the next L1 block. In normal operations, these will be new
L1 blocks as they get created, though we can also read old blocks while syncing, or in case of an L1 [re-org][g-reorg].
### L1 Retrieval
In the *L1 Retrieval* stage, we read the block we get from the outer stage (L1 traversal), and extract data for it. In
particular we extract a byte string that corresponds to the concatenation of the data in all the [batcher
transaction][g-batcher-transaction] belonging to the block. This byte stream encodes a stream of [channel
frames][g-channel-frame] (see the [Batch Submission Wire Format][wire-format] section for more info).
This frames are parsed, then grouped per [channel][g-channel] into a structure we call the *channel bank*.
Some frames are ignored:
- Frames where `frame.frame_number <= highest_frame_number`, where `highest_frame_number` is the highest frame number
that was previously encountered for this channel.
- i.e. in case of duplicate frame, the first frame read from L1 is considered canonical.
- Frames with a higher number than that of the final frame of the channel (i.e. the first frame marked with
`frame.is_last == 1`) are ignored.
- These frames could still be written into the channel bank if we haven't seen the final frame yet. But they will
never be read out from the channel bank.
### Channel Bank
The *Channel Bank* stage is responsible from reading from the channel bank that was written to by the L1 retrieval
stage, and decompressing batches from these frames.
In principle, we should be able to read any channel that has any number of sequential frames at the "front" of the
channel (i.e. right after any frames that have been read from the bank already) and decompress batches from them. (Note
that if we did this, we'd need to keep partially decompressed batches around.)
However, our current implementation doesn't support streaming decompression, so currently we have to wait until either:
- We have received all frames in the channel (i.e. we received the last frame in the channel (`is_last == 1`) and every
frame with a lower number).
- The channel has timed out (in which we case we read all contiguous sequential frames from the start of the channel).
- A channel is considered to be *timed out* if `currentL1Block.timestamp > channeld_id.timestamp + CHANNEL_TIMEOUT`.
- where `currentL1Block` is the L1 block maintained by this stage, which is the most recent L1 block whose frames
have been added to the channel bank.
> **TODO** There is currently `MAX_CHANNEL_BANK_SIZE`, a notion about the maximum amount of channels we can keep track
> of.
>
> - Is this a semantic detail (i.e. if the batcher opens too many frames, valid channels can be dropped?)
> - If so, I feel **very strongly** about changing this. This ties us very much to the current implementation.
> - And it doesn't feel necessary given the channel timeout - if DOS is an issue we can reduce the channel timeout.
> **TODO** The channel queue is a bit weird as implemented (blocks all other channels until the first channel is closed
> / timed out. Also unclear why we need to wait for channel closure. Maybe something to revisit?
>
> cf. slack discussion with Proto
### Batch Decoding
In the *Batch Decoding* stage, we decompress the frames we received in the last stage, then parse
[batches][g-sequencer-batch] from the decompressed byte stream.
### Batch Buffering
[batch-buffering]: #batch-buffering
During the *Batch Buffering* stage, we reorder batches by their timestamps. If batches are missing for some [time
slots][g-time-slot] and a valid batch with a higher timestamp exists, this stage also generates empty batches to fill
the gaps.
Batches are pushed to the next stage whenever there is one or more sequential batches directly following the timestamp
of the current [safe L2 head][g-safe-l2-head] (the last block that can be derived from the canonical L1 chain).
Note that the presence of any gaps in the batches derived from L1 means that this stage will need to buffer for a whole
[sequencing window][g-sequencing-window] before it can generate empty batches (because the missing batch(es) could have
data in the last L1 block of the window in the worst case).
We also ignore invalid batches, which do not satisfy one of the following constraints:
- The timestamp is aligned to the [block time][g-block-time]:
`(batch.timestamp - genesis_l2_timestamp) % block_time == 0`
- The timestamp is within the allowed range: `min_l2_timestamp <= batch.timestamp < max_l2_timestamp`, where
- all these values are denominated in seconds
- `min_l2_timestamp = prev_l2_timestamp + l2_block_time`
- `prev_l2_timestamp` is the timestamp of the previous L2 block: the last block of the previous epoch,
or the L2 genesis block timestamp if there is no previous epoch.
- `l2_block_time` is a configurable parameter of the time between L2 blocks (on Optimism, 2s)
- `max_l2_timestamp = max(l1_timestamp + max_sequencer_drift, min_l2_timestamp + l2_block_time)`
- `l1_timestamp` is the timestamp of the L1 block associated with the L2 block's epoch
- `max_sequencer_drift` is the maximum amount of time an L2 block's timestamp is allowed to get ahead of the
timestamp of its [L1 origin][g-l1-origin]
- Note that we always have `min_l2_timestamp >= l1_timestamp`, i.e. a L2 block timestamp is always equal or ahead of
the timestamp of its [L1 origin][g-l1-origin].
- The batch is the first batch with `batch.timestamp` in this sequencing window, i.e. one batch per L2 block number.
- The batch only contains sequenced transactions, i.e. it must NOT contain any [deposited-type transactions][
g-deposit-tx-type].
> **TODO** specify `max_sequencer_drift`
### Payload Attributes Derivation
In the *Payload Attributes Derivation* stage, we convert the batches we get from the previous stage into instances of
the [`PayloadAttributes`][g-payload-attr] structure. Such a structure encodes the transactions that need to figure into
a block, as well as other block inputs (timestamp, fee recipient, etc). Payload attributes derivation is detailed in the
section [Deriving Payload Attributes section][deriving-payload-attr] below.
### Engine Queue
In the *Engine Queue* stage, the previously derived `PayloadAttributes` structures are buffered and sent to the
[execution engine][g-exec-engine] to be executed and converted into a proper L2 block.
The engine queue maintains references to two L2 blocks:
- The [safe L2 head][g-safe-l2-head]: everything up to and including this block can be fully derived from the
canonical L1 chain.
- The [unsafe L2 head][g-unsafe-l2-head]: blocks between the safe and unsafe heads are [unsafe
blocks][g-unsafe-l2-block] that have not been derived from L1. These blocks either come from sequencing (in sequencer
mode) or from [unsafe sync][g-unsafe-sync] to the sequencer (in validator mode).
If the unsafe head is ahead of the safe head, then [consolidation][g-consolidation] is attempted.
During consolidation, we consider the oldest unsafe L2 block, i.e. the unsafe L2 block directly after the safe head. If
the payload attributes match this oldest unsafe L2 block, then that block can be considered "safe" and becomes the new
safe head.
In particular, the following fields of the payload attributes are checked for equality with the block:
- `parent_hash`
- `timestamp`
- `randao`
- `fee_recipient`
- `transactions_list` (first length, then equality of each of the encoded transactions)
If consolidation fails, the unsafe L2 head is reset to the safe L2 head.
If the safe and unsafe L2 heads are identical (whether because of failed consolidation or not), we send the block to the
execution engine to be converted into a proper L2 block, which becomes both the new L2 safe and unsafe heads.
Interaction with the execution engine via the execution engine API is detailed in the [Communication with the Execution
Engine][exec-engine-comm] section.
### Resetting the Pipeline
It is possible to reset the pipeline, for instance if we detect an L1 [re-org][g-reorg]. For more details on this, see
the [Handling L1 Re-Orgs][handling-reorgs] section.
------------------------------------------------------------------------------------------------------------------------
# Deriving Payload Attributes
[deriving-payload-attr]: #deriving-payload-attributes
For every L2 block we wish to create, we need to build [payload attributes][g-payload-attr],
represented by an [expanded version][expanded-payload] of the [`PayloadAttributesV1`][eth-payload] object,
which includes the additional `transactions` and `noTxPool` fields.
[expanded-payload]: exec-engine.md#extended-payloadattributesv1
[eth-payload]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1
## Deriving the Transaction List
For each such block, we start from a [sequencer batch][g-sequencer-batch] matching the target L2 block number. This
could potentially be an empty auto-generated batch, if the L1 chain did not include a batch for the target L2 block
number. [Remember][batch-format] the batch includes a [sequencing epoch][g-sequencing-epoch] number, an L2 timestamp,
and a transaction list.
This block is part of a [sequencing epoch][g-sequencing-epoch],
whose number matches that of an L1 block (its *[L1 origin][g-l1-origin]*).
This L1 block is used to derive L1 attributes and (for the first L2 block in the epoch) user deposits.
Therefore, a [`PayloadAttributesV1`][expanded-payload] object must include the following transactions:
- one or more [deposited transactions][g-deposited], of two kinds:
- a single *[L1 attributes deposited transaction][g-l1-attr-deposit]*, derived from the L1 origin.
- for the first L2 block in the epoch, zero or more *[user-deposited transactions][g-user-deposited]*, derived from
the [receipts][g-receipts] of the L1 origin.
- zero or more *[sequenced transactions][g-sequencing]*: regular transactions signed by L2 users, included in the
sequencer batch.
Transactions **must** appear in this order in the payload attributes.
The L1 attributes are read from the L1 block header, while deposits are read from the L1 block's [receipts][g-receipts].
Refer to the [**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log
entries.
[deposit-contract-spec]: deposits.md#deposit-contract
## Building Individual Payload Attributes
[payload attributes]: #building-individual-payload-attributes
After deriving the transaction list, the rollup node constructs a [`PayloadAttributesV1`][expanded-payload] as follows:
- `timestamp` is set to the batch's timestamp.
- `random` is set to the *random* `prev_randao` L1 block attribute.
- `suggestedFeeRecipient` is set to an address determined by the system.
- `transactions` is the array of the derived transactions: deposited transactions and sequenced transactions, all
encoded with [EIP-2718].
- `noTxPool` is set to `true`, to use the exact above `transactions` list when constructing the block.
[expanded-payload]: exec-engine.md#extended-payloadattributesv1
> **TODO** specify Optimism mainnet fee recipient
------------------------------------------------------------------------------------------------------------------------
# WARNING: BELOW THIS LINE, THE SPEC HAS NOT BEEN REVIEWED AND MAY CONTAIN MISTAKES
We still expect that the explanations here should be pretty useful.
------------------------------------------------------------------------------------------------------------------------
# Communication with the Execution Engine
[exec-engine-comm]: #communication-with-the-execution-engine
The [engine queue] is responsible for interacting with the execution engine, sending it
[`PayloadAttributesV1`][expanded-payload] objects and receiving L2 block references as a result. This happens whenever
the [safe L2 head][g-safe-l2-head] and the [unsafe L2 head][g-unsafe-l2-head] are identical, either because [unsafe
block consolidation][g-consolidation] failed or because no [unsafe L2 blocks][g-unsafe-l2-block] were known in the first
place. This section explains how this happens.
> **Note**: This only describes interaction with the execution engine in the context of L2 chain derivation from L1. The
> sequencer also interacts with the engine when it needs to create new L2 blocks using L2 transactions submitted by
> users.
Let:
- `refL2` be the (hash of) the current [safe L2 head][g-unsafe-l2-head]
- `finalizedRef` be the (hash of) the [finalized L2 head][g-finalized-l2-head]: the highest L2 block that can be fully
derived from *[finalized][finality]* L1 blocks — i.e. L1 blocks older than two L1 epochs (64 L1 [time
slots][g-time-slot]).
- `payloadAttributes` be some previously derived [payload attributes][g-payload-attr] for the L2 block with number
`l2Number(refL2) + 1`
[finality]: https://hackmd.io/@prysmaticlabs/finality
Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine:
```javascript
// request a new execution payload
forkChoiceState = {
headBlockHash: refL2,
safeBlockHash: refL2,
finalizedBlockHash: finalizedRef,
}
[status, payloadID, rpcErr] = engine_forkchoiceUpdatedV1(forkChoiceState, payloadAttributes)
if (rpcErr != null) soft_error()
if (status != "VALID") payload_error()
// retrieve and execute the execution payload
[executionPayload, rpcErr] = engine_getPayloadV1(payloadID)
if (rpcErr != null) soft_error()
[status, rpcErr] = engine_newPayloadV1(executionPayload)
if (rpcErr != null) soft_error()
if (status != "VALID") payload_error()
refL2 = l2Hash(executionPayload)
// update head to new refL2
forkChoiceState = {
headBlockHash: refL2,
safeBlockHash: refL2,
finalizedBlockHash: finalizedRef,
}
[status, payloadID, rpcErr] = engine_forkchoiceUpdatedV1(forkChoiceState, null)
if (rpcErr != null) soft_error()
if (status != "SUCCESS") payload_error()
```
As should apparent from the assignations, within the `forkChoiceState` object, the properties have the following
meaning:
- `headBlockHash`: block hash of the last block of the L2 chain, according to the sequencer.
- `safeBlockHash`: same as `headBlockHash`.
- `finalizedBlockHash`: the hash of the L2 block that can be fully derived from finalized L1 data, making it impossible
to derive anything else.
Error handling:
- A `payload_error()` means the inputs were wrong, and the payload attributes should thus be dropped from the queue, and
not reattempted.
- A `soft_error()` means that the interaction failed by chance, and should be reattempted.
- If the function completes without error, the attributes were applied successfully,
and can be dropped from the queue while the tracked "safe head" is updated.
> **TODO** `finalizedRef` is not being changed yet, but can be set to point to a L2 block fully derived from data up to
> a finalized L1 block.
The following JSON-RPC methods are part of the [execution engine API][exec-engine]:
[exec-engine]: exec-engine.md
- [`engine_forkchoiceUpdatedV1`] — updates the forkchoice (i.e. the chain head) to `headBlockHash` if different, and
instructs the engine to start building an execution payload given payload attributes the second argument isn't `null`
- [`engine_getPayloadV1`] — retrieves a previously requested execution payload
- [`engine_newPayloadV1`] — executes an execution payload to create a block
[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1
[`engine_getPayloadV1`]: exec-engine.md#engine_newPayloadV1
[`engine_newPayloadV1`]: exec-engine.md#engine_newPayloadV1
The execution payload is an object of type [`ExecutionPayloadV1`][eth-payload].
[eth-payload]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1
------------------------------------------------------------------------------------------------------------------------
# Handling L1 Re-Orgs
[handling-reorgs]: #handling-l1-re-orgs
The [L2 chain derivation pipeline][pipeline] as described above assumes linear progression of the L1 chain.
If the L1 chain [re-orgs][g-reorg], the rollup node must re-derive sections of the L2 chain such that it derives the
same L2 chain that a rollup node would derive if it only followed the new L1 chain.
A re-org can be recovered without re-deriving the full L2 chain, by resetting each pipeline stage from end (Engine
Queue) to start (L1 Traversal).
The general idea is to backpropagate the new L1 head through the stages, and reset the state in each stage so that the
stage will next process data originating from that block onwards.
## Resetting the Engine Queue
The engine queue maintains references to two L2 blocks:
- The safe L2 block (or *safe head*): everything up to and including this block can be fully derived from the
canonical L1 chain.
- The unsafe L2 block (or *unsafe head*): blocks between the safe and unsafe heads are blocks that have not been
derived from L1. These blocks either come from sequencing (in sequencer mode) or from "unsafe sync" to the sequencer
(in validator mode).
When resetting the L1 head, we need to rollback the safe head such that the L1 origin of the new safe head is a
canonical L1 block (i.e. an the new L1 head, or one of its ancestors). We achieved this by walking back the L2 chain
(starting from the current safe head) until we find such an L2 block. While doing this, we must take care not to walk
past the [L2 genesis][g-l2-genesis] or L1 genesis.
The unsafe head does not necessarily need to be reset, as long as its L1 origin is *plausible*. The L1 origin of the
unsafe head is considered plausible as long as it is in the canonical L1 chain or is ahead (higher number) than the head
of the L1 chain. When we determine that this is no longer the case, we reset the unsafe head to be equal to the safe
head.
> **TODO** Don't we always need to discard the unsafe head when there is a L1 re-org, because the unsafe head's origin
> builds on L1 blocks that have been re-orged away?
>
> I'm guessing maybe we received some unsafe blocks that build upon the re-orged L2, which we accept without relating
> them back to the safe head?
## Resetting Payload Attribute Derivation
In payload attribute derivation, we need to ensure that the L1 head is reset to the safe L2 head's L1 origin. In the
worst case, this would be as far back as `SWS` ([sequencing window][g-sequencing-window] size) blocks before the engine
queue's L1 head.
In the worst case, a whole sequencing window of L1 blocks was required to derive the L2 safe head (meaning that
`safeL2Head.l1Origin == engineQueue.l1Head - SWS`). This means that to derive the next L2 block, we have to read data
derived from L1 block `engineQueue.l1Head - SWS` and onwards, hence the need to reset the L1 head back to that value for
this stage.
However, in general, it is only necessary to reset as far back as `safeL2Head.l1Origin`, since it marks the start of the
sequencing window for the safe L2 head's epoch. As such, the next L2 block never depends on data derived from L1 blocks
before `safeL2Head.l1Origin`.
> **TODO** in the implementation, we always rollback by SWS, which is unecessary
> Quote from original spec:"We must find the first L2 block whose complete sequencing window is unchanged in the reorg."
> **TODO** sanity check this section, it was incorrect in previous spec, and confused me multiple times
## Resetting Batch Decoding
The batch decoding stage is simply reset by resetting its L1 head to the payload attribute derivation stage's L1 head.
(The same reasoning as the payload derivation stage applies.)
## Resetting Channel Buffering
> **Note**: in this section, the term *next (L2) block* will refer to the block that will become the next L2 safe head.
> **TODO** The above can be changed in the case where we always reset the unsafe head to the safe head upon L1 re-org.
> (See TODO above in "Resetting the Engine Queue")
Because we group [sequencer batches][g-sequencer-batch] into [channels][g-channel], it means that decoding a batch that
has data posted (in a [channel frame][g-channel-frame]) within the sequencing window of its epoch might require [channel
frames][g-channel-frame] posted before the start of the [sequencing window][g-sequencing-window]. Note that this is only
possible if we start sending channel frames before knowing all the batches that will go into the channel.
In the worst case, decoding the batch for the next L2 block would require reading the last frame from a channel, posted
in a [batcher transaction][g-batcher-transaction] in `safeL2Head.l1Origin + 1` (second L1 block of the next L2 block's
epoch sequencing window, assuming it is in the same epoch as `safeL2Head`).
> **Note**: In reality, there are no checks or constraints preventing the batch from landing in `safeL2Head.l1Origin`.
> However this would be strange, because the next L2 block is built after the current L2 safe block, which requires
> reading the deposits L1 attributes and deposits from `safeL2Head.l1Origin`. Still, a wonky or misbehaving sequencer
> could post a batch for the L2 block `safeL2Head + 1` on L1 block `safeL2Head.1Origin`.
Keeping things worst case, `safeL2Head.l1Origin` would also be the last allowable block for the frame to land. The
allowed time range for frames within a channel to land on L1 is `[channel_id.timestamp, channel_id.timestamp +
CHANNEL_TIMEOUT]`. The allowed L1 block range for these frames are any L1 block whose timestamp falls inside this time
range.
Therefore, to be safe, we can reset the L1 head of Channel Buffering to the oldest L1 block whose timestamp is higher
than `safeL2Head.l1Origin.timestamp - CHANNEL_TIMEOUT`.
> **Note**: The above is what the implementation currently does.
In reality it's only strictly necessary to reset the oldest L1 block whose timestamp is higher than the oldest
`channel_id.timestamp` found in the batcher transaction that is not older than `safeL2Head.l1Origin.timestamp -
CHANNEL_TIMEOUT`.
We define `CHANNEL_TIMEOUT = 600`, i.e. 10 hours.
> **TODO** does `CHANNEL_TIMEOUT` have a relationship with `SWS`?
>
> I think yes, it has to be shorter than `SWS` but ONLY if we can't do streaming decryption (the case currently).
> Otherwise it could be shorter or longer.
— and explain its relationship with `SWS` if any?
This situation is the main purpose of the [channel timeout][g-channel-timeout]: without the timeout, we might have to
look arbitrarily far back on L1 to be able to decompress batches, which is not acceptable for performance reasons.
The other puprose of the channel timeout is to avoid having the rollup node keep old unclosed channel data around
forever.
Once the L1 head is reset, we then need to discard any frames read from blocks more recent than this updated L1 head.
## Resetting L1 Retrieval & L1 Traversal
These are simply reset by resetting their L1 head to `channelBuffering.l1Head`, and dropping any buffered data.
## Reorgs Post-Merge
Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs, or
approximately 12 minutes, unless an attacker controls more than 1/3 of the total stake).
[merge]: https://ethereum.org/en/upgrades/merge/
[l1-finality]: https://ethereum.org/en/developers/docs/consensus-mechanisms/pos/#finality
> **TODO** This was in the spec:
>
> In practice, we'll pick an already-finalized L1 block as L2
> inception point to preclude the possibility of a re-org past genesis, at the cost of a few empty blocks at the start
> of the L2 chain.
>
> This makes sense, but is in conflict with how the [L2 chain inception][g-l2-chain-inception] is currently determined,
> which is via the L2 output oracle deployment & upgrades.
...@@ -4,18 +4,17 @@ ...@@ -4,18 +4,17 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [L2 Execution Engine](#l2-execution-engine) - [Deposited transaction processing](#deposited-transaction-processing)
- [Deposited transaction processing](#deposited-transaction-processing) - [Deposited transaction boundaries](#deposited-transaction-boundaries)
- [Deposited transaction boundaries](#deposited-transaction-boundaries) - [Engine API](#engine-api)
- [Engine API](#engine-api) - [`engine_forkchoiceUpdatedV1`](#engine_forkchoiceupdatedv1)
- [`engine_forkchoiceUpdatedV1`](#engine_forkchoiceupdatedv1) - [Extended PayloadAttributesV1](#extended-payloadattributesv1)
- [Extended PayloadAttributesV1](#extended-payloadattributesv1) - [`engine_newPayloadV1`](#engine_newpayloadv1)
- [`engine_newPayloadV1`](#engine_newpayloadv1) - [`engine_getPayloadV1`](#engine_getpayloadv1)
- [`engine_getPayloadV1`](#engine_getpayloadv1) - [Networking](#networking)
- [Networking](#networking) - [Sync](#sync)
- [Sync](#sync) - [Happy-path sync](#happy-path-sync)
- [Happy-path sync](#happy-path-sync) - [Worst-case sync](#worst-case-sync)
- [Worst-case sync](#worst-case-sync)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Glossary](#glossary)
- [General Terms](#general-terms) - [General Terms](#general-terms)
- [Layer 1 (L1)](#layer-1-l1) - [Layer 1 (L1)](#layer-1-l1)
- [Layer 2 (L2)](#layer-2-l2) - [Layer 2 (L2)](#layer-2-l2)
...@@ -18,9 +17,10 @@ ...@@ -18,9 +17,10 @@
- [Fork Choice Rule](#fork-choice-rule) - [Fork Choice Rule](#fork-choice-rule)
- [Priority Gas Auction](#priority-gas-auction) - [Priority Gas Auction](#priority-gas-auction)
- [Sequencing](#sequencing) - [Sequencing](#sequencing)
- [Sequencing window](#sequencing-window) - [Sequencer](#sequencer)
- [Sequencing epoch](#sequencing-epoch) - [Sequencing Window](#sequencing-window)
- [Sequencer batch](#sequencer-batch) - [Sequencing Epoch](#sequencing-epoch)
- [L1 Origin](#l1-origin)
- [Deposits](#deposits) - [Deposits](#deposits)
- [Deposited Transaction](#deposited-transaction) - [Deposited Transaction](#deposited-transaction)
- [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction) - [L1 Attributes Deposited Transaction](#l1-attributes-deposited-transaction)
...@@ -32,16 +32,38 @@ ...@@ -32,16 +32,38 @@
- [Deposit Contract](#deposit-contract) - [Deposit Contract](#deposit-contract)
- [Withdrawals](#withdrawals) - [Withdrawals](#withdrawals)
- [Relayer](#relayer) - [Relayer](#relayer)
- [Finalization Period](#finalization-period)
- [Batch Submission](#batch-submission)
- [Data Availability](#data-availability)
- [Data Availability Provider](#data-availability-provider)
- [Sequencer Batch](#sequencer-batch)
- [Channel](#channel)
- [Channel Frame](#channel-frame)
- [Batcher](#batcher)
- [Batcher Transaction](#batcher-transaction)
- [Channel Timeout](#channel-timeout)
- [L2 Chain Derivation](#l2-chain-derivation)
- [L2 Derivation Inputs](#l2-derivation-inputs)
- [Payload Attributes](#payload-attributes)
- [L2 Genesis Block](#l2-genesis-block)
- [L2 Chain Inception](#l2-chain-inception)
- [Safe L2 Head](#safe-l2-head)
- [Unsafe L2 Block](#unsafe-l2-block)
- [Unsafe L2 Head](#unsafe-l2-head)
- [Unsafe Block Consolidation](#unsafe-block-consolidation)
- [Finalized L2 Head](#finalized-l2-head)
- [Other L2 Chain Concepts](#other-l2-chain-concepts) - [Other L2 Chain Concepts](#other-l2-chain-concepts)
- [Address Aliasing](#address-aliasing) - [Address Aliasing](#address-aliasing)
- [L2 Chain Inception](#l2-chain-inception)
- [Rollup Node](#rollup-node) - [Rollup Node](#rollup-node)
- [Rollup Driver](#rollup-driver) - [Rollup Driver](#rollup-driver)
- [L2 Chain Derivation](#l2-chain-derivation)
- [L2 Derivation Inputs](#l2-derivation-inputs)
- [Payload Attributes](#payload-attributes)
- [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract) - [L1 Attributes Predeployed Contract](#l1-attributes-predeployed-contract)
- [L2 Output Root](#l2-output-root) - [L2 Output Root](#l2-output-root)
- [L2 Output Oracle Contract](#l2-output-oracle-contract)
- [Validator](#validator)
- [Fault Proof](#fault-proof)
- [Time Slot](#time-slot)
- [Block Time](#block-time)
- [Unsafe Sync](#unsafe-sync)
- [Execution Engine Concepts](#execution-engine-concepts) - [Execution Engine Concepts](#execution-engine-concepts)
- [Execution Engine](#execution-engine) - [Execution Engine](#execution-engine)
...@@ -139,10 +161,8 @@ Different transaction types can contain different payloads, and be handled diffe ...@@ -139,10 +161,8 @@ Different transaction types can contain different payloads, and be handled diffe
The fork choice rule is the rule used to determined which block is to be considered as the head of a blockchain. On L1, The fork choice rule is the rule used to determined which block is to be considered as the head of a blockchain. On L1,
this is determined by the proof of stake rules. this is determined by the proof of stake rules.
L2 also has a fork choice rule, although the rules vary depending on whether we want the sequencer-confirmed head, the L2 also has a fork choice rule, although the rules vary depending on whether we want the [safe L2 head][safe-l2-head],
on-chain-confirmed head, or the on-chain-finalized head. the [unsafe L2 head][unsafe-l2-head] or the [finalized L2 head][finalized-l2-head].
> TODO: define and link to those concepts
## Priority Gas Auction ## Priority Gas Auction
...@@ -167,23 +187,47 @@ Transactions in the rollup can be included in two ways: ...@@ -167,23 +187,47 @@ Transactions in the rollup can be included in two ways:
Submitting transactions for inclusion in a batch saves costs by reducing overhead, and enables the sequencer to Submitting transactions for inclusion in a batch saves costs by reducing overhead, and enables the sequencer to
pre-confirm the transactions before the L1 confirms the data. pre-confirm the transactions before the L1 confirms the data.
## Sequencing window ## Sequencer
[sequencer]: glossary.md#sequencer
A sequencer is either a [rollup node][rollup-node] ran in sequencer mode, or the operator of this rollup node.
The sequencer is a priviledged actor, which receives L2 transactions from L2 users, creates L2 blocks using them, which
it then submits to [data availability provider][avail-provider] (via a [batcher]). It also submits [output
roots][l2-output] to L1.
## Sequencing Window
[sequencing-window]: glossary.md#sequencing-window [sequencing-window]: glossary.md#sequencing-window
A sequencing window is a range of L1 blocks, to parse inputs from during a derivation step. A sequencing window is a range of L1 blocks from which a [sequencing epoch][sequencing-epoch] can be derived.
## Sequencing epoch A sequencing window whose first L1 block has number `N` contains [batcher transactions][batcher-transactions] for epoch
`N`. The window contains blocks `[N, N + SWS)` where `SWS` is the sequencer window size.
A sequencing epoch is a number identifying the start of a [sequencing window](#sequencing-window), > **TODO** specify sequencer window size
equal to the L1 block number of the first block in the window.
## Sequencer batch Additionally, the first block in the window defines the [depositing transactions][depositing-tx] which determine the
[deposits] to be included in the first L2 block of the epoch.
[sequencer-batch]: glossary.md#sequencer-batch ## Sequencing Epoch
[sequencing-epoch]: glossary.md#sequencing-epoch
A sequencing epoch is sequential range of L2 blocks derived from a [sequencing window](#sequencing-window) of L1 blocks.
Each epoch is identified by an epoch number, which is equal to the block number number of the first L1 block in the
sequencing window.
A sequencer batch is list of L2 transactions tagged with an [`epoch`](#sequencing-epoch) and L2 block `timestamp`. Epochs can have variable size, subject to some constraints. See the [L2 chain derivation specification][derivation-spec]
Each L2 block can have one batch of transactions, an input for the block derivation. for more details.
## L1 Origin
[l1-origin]: glossary.md#l1-origin
The L1 origin of an L2 block is the L1 block corresponding to its [sequencing epoch][sequencing-epoch].
------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------
...@@ -260,7 +304,7 @@ specification. ...@@ -260,7 +304,7 @@ specification.
A *depositing call* is an L1 call to the [deposit contract][deposit-contract], which will be derived to a A *depositing call* is an L1 call to the [deposit contract][deposit-contract], which will be derived to a
[user-deposited transaction][user-deposited] by the [rollup driver]. [user-deposited transaction][user-deposited] by the [rollup driver].
This call specifies all the data (destination, value, calldata, ...) for the deposited transaction. "submits* This call specifies all the data (destination, value, calldata, ...) for the deposited transaction.
## Depositing Transaction ## Depositing Transaction
...@@ -282,12 +326,16 @@ call][depositing-call]. The *depositor* is **NOT** the originator of the deposit ...@@ -282,12 +326,16 @@ call][depositing-call]. The *depositor* is **NOT** the originator of the deposit
The *deposited transaction type* is an [EIP-2718] [transaction type][transaction-type], which specifies the input fields The *deposited transaction type* is an [EIP-2718] [transaction type][transaction-type], which specifies the input fields
and correct handling of a [deposited transaction][deposited]. and correct handling of a [deposited transaction][deposited].
See the [corresponding section][spec-deposit-tx-type] of the deposits spec for more information.
[spec-deposit-tx-type]: deposits.md#the-deposited-transaction-type
## Deposit Contract ## Deposit Contract
[deposit-contract]: glossary.md#deposit-contract [deposit-contract]: glossary.md#deposit-contract
The *deposit contract* is qn [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are The *deposit contract* is qn [L1] contract to which [EOAs][EOA] and contracts may send [deposits]. The deposits are
emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup node]. emitted as log records (in Solidity, these are called *events*) for consumption by [rollup nodes][rollup-node].
Advanced note: the deposits are not stored in calldata because they can be sent by contracts, in which case the calldata Advanced note: the deposits are not stored in calldata because they can be sent by contracts, in which case the calldata
is part of the *internal* execution between contracts, and this intermediate calldata is not captured in one of the is part of the *internal* execution between contracts, and this intermediate calldata is not captured in one of the
...@@ -299,6 +347,8 @@ cf. [Deposits Specification](deposits.md) ...@@ -299,6 +347,8 @@ cf. [Deposits Specification](deposits.md)
# Withdrawals # Withdrawals
> **TODO** expand this whole section to be clearer
[withdrawals]: glossary.md#withdrawals [withdrawals]: glossary.md#withdrawals
In general, a withdrawal is a transaction sent from L2 to L1 that may transfer data and/or value. In general, a withdrawal is a transaction sent from L2 to L1 that may transfer data and/or value.
...@@ -316,55 +366,154 @@ The term *withdrawal* is somewhat ambiguous as these "transactions" exist at mul ...@@ -316,55 +366,154 @@ The term *withdrawal* is somewhat ambiguous as these "transactions" exist at mul
An EOA on L1 which finalizes a withdrawal by submitting the data necessary to verify its inclusion on L2. An EOA on L1 which finalizes a withdrawal by submitting the data necessary to verify its inclusion on L2.
## Finalization Period
[finalization-period]: glossary.md#finalization-period
The finalization period — sometimes also called *withdrawal delay* — is the minimum amount of time (in seconds) that
must elapse before a [withdrawal][withrawals] can be finalized.
The finalization period is necessary to afford sufficient time for [validators][validator] to make a [fault
proof][fault-proof].
> **TODO** specify current value for finalization period
------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------
# Other L2 Chain Concepts # Batch Submission
## Address Aliasing [batch-submission]: glossary.md#batch-submission
[address-aliasing]: glossary.md#address-aliasing ## Data Availability
When a contract submits a [deposit][deposits] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) will be [data-availability]: glossary.md#data-availability
aliased with a modified representation of the address of a contract.
- cf. [Deposit Specification](deposits.md#address-aliasing) Data availability is the guarantee that some data will be "available" (i.e. *retrievable*) during a reasonably long time
window. In Optimism's case, the data in question are [sequencer batches][sequencer-batch] that [validators][validator]
needs in order to verify the sequencer's work and validate the L2 chain.
## L2 Chain Inception The [finalization period][finalization-period] should be taken as the lower bound on such the availability window, since
that is when data availability is the most crucial, as it is needed to perform a [fault proof][fault-proof].
[L2 chain inception]: glossary.md#L2-chain-inception "Availability" **does not** mean guaranteed long-term storage of the data.
The L1 block number for which the first block of the L2 chain was generated. ## Data Availability Provider
## Rollup Node [avail-provider]: glossary.md#data-availability-provider
[rollup node]: glossary.md#rollup-node A data availability provider is a service that can be used to make data available. See the [Data
Availability][data-availability] for more information on what this means.
The rollup node is responsible for [deriving the L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their Ideally, a good data availability provider such provide strong *verifiable* guarantees of data availability
associated [receipts][receipt]). This is done by its [rollup driver] component.
- cf. [Rollup Node Specification](rollup-node.md) Currently, the only supported data availability provider is Ethereum call data. [Ethereum data blobs][eip4844] will be
supported when they get deployed on Ethereum.
## Rollup Driver ## Sequencer Batch
[rollup driver]: glossary.md#rollup-driver [sequencer-batch]: glossary.md#sequencer-batch
A sequencer batch is list of L2 transactions (that were submitted to a sequencer) tagged with an [epoch
number](#sequencing-epoch) and an L2 block timestamp (which can trivially be converted to a block number, given our
block time is constant).
Sequencer batches are part of the [L2 derivation inputs][deriv-inputs]. Each batch represents the inputs needed to build
**one** L2 block (given the existing L2 chain state) — excepted for the fist block of each epoch, which also needs
information about deposits (cf. the section on [L2 derivation inputs][deriv-inputs]).
The rollup driver is the [rollup node] component responsible for [deriving the L2 chain][derivation] from the L1 chain ## Channel
(L1 [blocks][block] and their associated [receipts][receipt]).
## L2 Chain Derivation [channel]: glossary.md#channel
A channel is a sequence of [sequencer batches][sequencer-batch] (for sequential blocks) compressed together. The reason
to group multiple batches together is simply to obtain a better compression rate, hence reducing data availability
costs.
A channel can be split in [frames][channel-frame] in order to be transmitted via [batcher
transactions][batcher-transaction]. The reason to split a channel into frames is that a channel might too large to
include in a single batcher transaction.
A channel is uniquely identified by its timestamp (UNIX time at which the channel was created) and a random value. See
the [Frame Format][frame-format] section of the L2 Chain Derivation specifictaion for more information.
[frame-format]: derivation.md#frame-format
On the side of the [rollup node][rollup-node] (which is the consumer of channels), a channel is considered to be
*opened* if its final frame (explicitly marked as such) has not been read, or closed otherwise.
## Channel Frame
[channel-frame]: glossary.md#channel-frame
A channel frame is a chunk of data belonging to a [channel]. [Batcher transactions][batcher-transaction] carry one or
multiple frames. The reason to split a channel into frames is that a channel might too large to include in a single
batcher transaction.
## Batcher
[batcher]: glossary.md#batcher
A batcher is a software component (independant program) that is responsible to make channels available on a data
availability provider. The batcher communicates with the rollup node in order to retrieve the channels. The channels are
then made available using [batcher transactions][batcher-transaction].
> **TODO** In the future, we might want to make the batcher responsible for constructing the channels, letting it only
> query the rollup node for L2 block inputs.
## Batcher Transaction
[batcher-transaction]: glossary.md#batcher-transaction
A batcher transaction is a transaction submitted by a [batcher] to a data availability provider, in order to make
channels available. These transactions carry one or more full frames, which may belong to different channels. A
channel's frame may be split between multiple batcher transactions.
When submitted to Ethereum calldata, the batcher transaction's receiver must be the sequencer inbox address. The
transaction must also be signed by a recognized batch submitter account.
> **TODO** specify where these recognized batch submitter accounts are stored
## Channel Timeout
[channel-timeout]: glossary.md#channel-timeout
The channel timeout is a duration (in seconds) during which [channel frames][channel-frame may land on L1 within
[batcher transactions][batcher-transaction].
The acceptable time range for the frames of a [channel][channel] is `[channel_id.timestamp, channel_id.timestamp +
CHANNEL_TIMEOUT]`. The acceptable L1 block range for these frames are any L1 block whose timestamp falls inside this
time range. (Note that `channel_id.timetamp` must be lower than the L1 block timestamp of any L1 block in which frames
of the channel are seen, or else these frames are ignored.)
The purpose of channel timeouts is dual:
- Avoid keeping old unclosed channel data around forever (an unclosed channel is a channel whose final frame was not
sent).
- Bound the number of L1 blocks we have to look back in order to decode [sequencer batches][sequencer-batch] from
channels. This is particularly relevant during L1 re-orgs, see the [Resetting Channel Buffering][reset-channel-buffer]
section of the L2 Chain Derivation specifiction for more information.
[reset-channel-buffer]: derivation.md#resetting-channel-buffering
> **TODO** specify `CHANNEL_TIMEOUT`
------------------------------------------------------------------------------------------------------------------------
# L2 Chain Derivation
[derivation]: glossary.md#L2-chain-derivation [derivation]: glossary.md#L2-chain-derivation
A process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to derive the L2 chain. L2 chain derivation is a process that reads [L2 derivation inputs][deriv-inputs] from L1 in order to derive the L2
chain.
cf. [L2 Chain Derivation (in Rollup Node See the [L2 chain derivation specification][derivation-spec] for more details.
Specification)](rollup-node.md#l2-chain-derivation)
## L2 Derivation Inputs ## L2 Derivation Inputs
[deriv-inputs]: glossary.md#l2-chain-derivation-inputs [deriv-inputs]: glossary.md#l2-chain-derivation-inputs
This term refers to data that is found in L1 blocks and is read by the [rollup node] to construct [payload attributes]. This term refers to data that is found in L1 blocks and is read by the [rollup node][rollup-node] to construct [payload
attributes][payload-attr].
L2 derivation inputs include: L2 derivation inputs include:
...@@ -377,7 +526,7 @@ L2 derivation inputs include: ...@@ -377,7 +526,7 @@ L2 derivation inputs include:
## Payload Attributes ## Payload Attributes
[payload attributes]: glossary.md#payload-attributes [payload-attr]: glossary.md#payload-attributes
This term refers to an object that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are This term refers to an object that can be derived from [L2 chain derivation inputs][deriv-inputs] found on L1, which are
then passed to the [execution engine][execution-engine] to construct L2 blocks. then passed to the [execution engine][execution-engine] to construct L2 blocks.
...@@ -391,6 +540,131 @@ See also the [Building The Payload Attributes][building-payload-attr] section of ...@@ -391,6 +540,131 @@ See also the [Building The Payload Attributes][building-payload-attr] section of
[building-payload-attr]: rollup-node.md#building-the-payload-attributes [building-payload-attr]: rollup-node.md#building-the-payload-attributes
## L2 Genesis Block
[l2-genesis]: glossary.md#l2-genesis-block
The L2 genesis block is the first block of the L2 chain in its current version.
The state of the L2 genesis block comprises:
- State inherited from the previous version of the L2 chain.
- This state was possibly modified by "state surgeries". For instance, the migration to Bedrock entailed changes on
how native ETH balances were stored in the storage trie.
- [Predeployed contracts][predeploy]
The timestap of the L2 genesis block must be a multiple of the [block time][block-time] (i.e. a even number, since the
block time is 2 seconds).
When updating the rollup protocol to a new version, we may perform a *squash fork*, a process that entails the creation
of a new L2 genesis block. This new L2 genesis block will have block number `X + 1`, where `X` is the block number of
the final L2 block before the update.
A squash fork is not to be confused with a *re-genesis*, a similar process that we employed in the past, which also
resets L2 block numbers, such that the new L2 genesis block has number 0. We will not employ re-genesis in the future.
Squash forks are superior to re-geneses because they avoid duplicating L2 block numbers, which breaks a lot of external
tools.
## L2 Chain Inception
[l2-chain-inception]: glossary.md#L2-chain-inception
The L1 block number at which the output roots for the [genesis block][l2-genesis] were proposed on the [output
oracle][output-oracle] contract.
In the current implementation, this is the L1 block number at which the output oracle contract was deployed or upgraded.
## Safe L2 Head
[safe-l2-head]: glossary.md#safe-l2-head
The safe L2 head is most recent L2 block that was can be derived entirely from L1 by a [rollup node][rollup-node]. This
can vary between different nodes, based on their view of the L1 chain.
## Unsafe L2 Block
[unsafe-l2-block]: glossary.md#unsafe-l2-block
An unsafe L2 block is an L2 block that a [rollup node][rollup-node] knows about, but which was not derived from the L1
chian. In sequencer mode, this will be a block sequenced by the sequencer itself. In validator mode, this will be a
block acquired from the sequencer via [unsafe sync][unsafe-sync].
## Unsafe L2 Head
[unsafe-l2-head]: glossary.md#unsafe-l2-head
The unsafe L2 head is the highest [unsafe L2 block][unsafe-l2-block] that a [rollup node][rollup-node] knows about.
## Unsafe Block Consolidation
[consolidation]: glossary.md#unsafe-block-consolidation
Unsafe block consolidation is the process through which the [rollup node][rollup-node] attempts to move the [safe L2
head] a block forward, so that the oldest [unsafe L2 block][unsafe-l2-block] becomes the new safe L2 head.
In order to perform consolidation, the node verifies that the [payload attributes][payload-attr] derived from the L1
chain match the oldest unsafe L2 block exactly.
See the [Engine Queue section][engine-queue] of the L2 chain derivatiaon spec for more information.
[engine-queue]: derivation.md#engine-queue
## Finalized L2 Head
[finalized-l2-head]: glossary.md#finalized-l2-head
The finalized L2 head is the highest L2 block that can be derived from *[finalized][finality]* L1 blocks — i.e. L1
blocks older than two L1 epochs (64 L1 [time slots][time-slot]).
[finality]: <https://hackmd.io/@prysmaticlabs/finality> *finalized* L1 data.
------------------------------------------------------------------------------------------------------------------------
# Other L2 Chain Concepts
## Address Aliasing
[address-aliasing]: glossary.md#address-aliasing
When a contract submits a [deposit][deposits] from L1 to L2, it's address (as returned by `ORIGIN` and `CALLER`) will be
aliased with a modified representation of the address of a contract.
- cf. [Deposit Specification](deposits.md#address-aliasing)
## Rollup Node
[rollup-node]: glossary.md#rollup-node
The rollup node is responsible for [deriving the L2 chain][derivation] from the L1 chain (L1 [blocks][block] and their
associated [receipts][receipt]).
The rollup node can run either in *validator* or *sequencer* mode.
In sequencer mode, the rollup node receives L2 transactions from users, which it uses to create L2 blocks. These are
then submitted to a [data availability provider][avail-provider] via [batch submission][batch-submission]. The L2 chain
derivation then acts as a sanity check and a way to detect L1 chain [re-orgs][reorg].
In validator mode, the rollup node performs derivation as indicated above, but is also able to "run ahead" of the L1
chain by getting blocks directly from the sequencer, in which case derivation serves to validate the sequencer's
behaviour.
A rollup node running in validator mode is sometimes called *a replica*.
> **TODO** expand this to include output root submission
See the [rollup node specification][rollup-node-spec] for more information.
## Rollup Driver
[rollup driver]: glossary.md#rollup-driver
The rollup driver is the [rollup node][rollup-node] component responsible for [deriving the L2 chain][derivation]
from the L1 chain (L1 [blocks][block] and their associated [receipts][receipt]).
> **TODO** delete this entry, alongside its reference — can be replaced by "derivation process" or "derivation logic"
> where needed
## L1 Attributes Predeployed Contract ## L1 Attributes Predeployed Contract
[l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract [l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract
...@@ -408,6 +682,70 @@ A 32 byte value which serves as a commitment to the current state of the L2 chai ...@@ -408,6 +682,70 @@ A 32 byte value which serves as a commitment to the current state of the L2 chai
cf. [Proposing L2 output commitments](proposals.md#l2-output-root-proposals-specification) cf. [Proposing L2 output commitments](proposals.md#l2-output-root-proposals-specification)
## L2 Output Oracle Contract
[output-oracle]: glossary.md#l2-output-oracle-contract
An L1 contract to which [L2 output roots][l2-output] are posted by the [sequencer].
> **TODO** expand
## Validator
[validator]: glossary.md#validator
A validator is an entity (individual or organization) that runs a [rollup node][rollup-node] in validator mode.
Doing so grants a lot of benefits similar to running an Ethereum node, such as the ability to simulate L2 transactions
locally, without rate limiting.
It also lets the validator verify the work of the [sequencer], by re-deriving [output roots][l2-output] and comparing
them against those submitted by the sequencer. In case of a mismatch, the validator can perform a [fault
proof][fault-proof].
## Fault Proof
[fault-proof]: glossary.md#fault-proof
An on-chain *interactive* proof, performed by [validators][validator], that demonstrates that a [sequencer] provided
erroneous [output roots][l2-output].
Fault proofs are not specified yet. For now, the best place to find information about fault proofs is the [Cannon
repository][cannon].
> **TODO** expand
## Time Slot
[time-slot]: glossary.md#time-slot
On L2, there is a block every 2 second (this duration is known as the [block time][block-time]).
We say that there is a "time slot" every multiple of 2s after the timestamp of the [L2 genesis block][l2-genesis].
On L1, post-[merge], the time slots are every 12s. However, an L1 block may not be produced for every time slot, in case
of even benign consensus issues.
## Block Time
[block-time]: glossary.md#block-time
The L2 block time is 2 second, meaning there is an L2 block at every 2s [time slot][time-slot].
Post-[merge], it could be said the that L1 block time is 12s as that is the L1 [time slot][time-slot]. However, in
reality the block time is variable as some time slots might be skipped.
Pre-merge, the L1 block time is variable, though it is on average 13s.
## Unsafe Sync
[unsafe-sync]: glossary.md#unsafe-sync
Unsafe sync is the process through which a [validator][validator] learns about [unsafe L2 blocks][unsafe-l2-block] from
the [sequencer][sequencer].
These unsafe blocks will later need to be confirmed by the L1 chain (via [unsafe block consolidation][consolidation]).
------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------
# Execution Engine Concepts # Execution Engine Concepts
...@@ -424,13 +762,17 @@ Both L1 (post-[merge]) and L2 have an execution engine. ...@@ -424,13 +762,17 @@ Both L1 (post-[merge]) and L2 have an execution engine.
On L1, the executed blocks can come from L1 block synchronization; or from a block freshly minted by the execution On L1, the executed blocks can come from L1 block synchronization; or from a block freshly minted by the execution
engine (using transactions from the L1 [mempool]), at the request of the L1 consensus layer. engine (using transactions from the L1 [mempool]), at the request of the L1 consensus layer.
On L2, the executed blocks are freshly minted by the execution engine at the request of the [rollup node], using On L2, the executed blocks are freshly minted by the execution engine at the request of the [rollup node][rollup-node],
transactions [derived from L1 blocks][derivation]. using transactions [derived from L1 blocks][derivation].
In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified. In these specifications, "execution engine" always refer to the L2 execution engine, unless otherwise specified.
- cf. [Execution Engine Specification](exec-engine.md) - cf. [Execution Engine Specification](exec-engine.md)
<!-- Internal Links -->
[derivation-spec]: derivation.md
[rollup-node-spec]: rollup-node.md
<!-- External Links --> <!-- External Links -->
[mpt-details]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md [mpt-details]: https://github.com/norswap/nanoeth/blob/d4c0c89cc774d4225d16970aa44c74114c1cfa63/src/com/norswap/nanoeth/trees/patricia/README.md
[trie]: https://en.wikipedia.org/wiki/Trie [trie]: https://en.wikipedia.org/wiki/Trie
...@@ -442,3 +784,5 @@ In these specifications, "execution engine" always refer to the L2 execution eng ...@@ -442,3 +784,5 @@ In these specifications, "execution engine" always refer to the L2 execution eng
[merge]: https://ethereum.org/en/eth2/merge/ [merge]: https://ethereum.org/en/eth2/merge/
[mempool]: https://www.quicknode.com/guides/defi/how-to-access-ethereum-mempool [mempool]: https://www.quicknode.com/guides/defi/how-to-access-ethereum-mempool
[L1 consensus layer]: https://github.com/ethereum/consensus-specs/#readme [L1 consensus layer]: https://github.com/ethereum/consensus-specs/#readme
[cannon]: https://github.com/ethereum-optimism/cannon
[eip4844]: https://www.eip4844.com/
...@@ -4,10 +4,9 @@ ...@@ -4,10 +4,9 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Guaranteed Gas Fee Market](#guaranteed-gas-fee-market) - [Gas Stipend](#gas-stipend)
- [Gas Stipend](#gas-stipend) - [Limiting Guaranteed Gas](#limiting-guaranteed-gas)
- [Limiting Guaranteed Gas](#limiting-guaranteed-gas) - [Rationale for burning L1 Gas](#rationale-for-burning-l1-gas)
- [Rationale for burning L1 Gas](#rationale-for-burning-l1-gas)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -4,21 +4,20 @@ ...@@ -4,21 +4,20 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Introduction](#introduction) - [Foundations](#foundations)
- [Foundations](#foundations) - [What is Ethereum scalability?](#what-is-ethereum-scalability)
- [What is Ethereum scalability?](#what-is-ethereum-scalability) - [What is an Optimistic Rollup?](#what-is-an-optimistic-rollup)
- [What is an Optimistic Rollup?](#what-is-an-optimistic-rollup) - [What is EVM Equivalence?](#what-is-evm-equivalence)
- [What is EVM Equivalence?](#what-is-evm-equivalence) - [🎶 All together now 🎶](#-all-together-now-)
- [🎶 All together now 🎶](#-all-together-now-) - [Protocol Guarantees](#protocol-guarantees)
- [Protocol Guarantees](#protocol-guarantees) - [Network Participants](#network-participants)
- [Network Participants](#network-participants) - [Users](#users)
- [Users](#users) - [Sequencers](#sequencers)
- [Sequencers](#sequencers) - [Verifiers](#verifiers)
- [Verifiers](#verifiers) - [Key Interaction Diagrams](#key-interaction-diagrams)
- [Key Interaction Diagrams](#key-interaction-diagrams) - [Depositing and Sending Transactions](#depositing-and-sending-transactions)
- [Depositing and Sending Transactions](#depositing-and-sending-transactions) - [Withdrawing](#withdrawing)
- [Withdrawing](#withdrawing) - [Next Steps](#next-steps)
- [Next Steps](#next-steps)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -4,13 +4,12 @@ ...@@ -4,13 +4,12 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Cross Domain Messengers](#cross-domain-messengers) - [Message Passing](#message-passing)
- [Message Passing](#message-passing) - [Upgradability](#upgradability)
- [Upgradability](#upgradability) - [Message Versioning](#message-versioning)
- [Message Versioning](#message-versioning) - [Message Version 0](#message-version-0)
- [Message Version 0](#message-version-0) - [Message Version 1](#message-version-1)
- [Message Version 1](#message-version-1) - [Backwards Compatibility Notes](#backwards-compatibility-notes)
- [Backwards Compatibility Notes](#backwards-compatibility-notes)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
# Bedrock Local Devnet Setup # Bedrock Local Devnet Setup
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
- [Bedrock Local Devnet Setup](#bedrock-local-devnet-setup)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
You can spin up a local devnet via `docker-compose`. You can spin up a local devnet via `docker-compose`.
For convenience, we have defined `make` targets to start and stop the devnet with a single command. For convenience, we have defined `make` targets to start and stop the devnet with a single command.
To run the devnet, you will need `docker` and `docker-compose` installed. To run the devnet, you will need `docker` and `docker-compose` installed.
......
# Versioning # Versioning
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
- [Go modules](#go-modules)
- [versioning process](#versioning-process)
- [Typescript](#typescript)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Go modules ## Go modules
Go modules that are currently versioned: Go modules that are currently versioned:
......
...@@ -4,19 +4,18 @@ ...@@ -4,19 +4,18 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Optimism Overview](#optimism-overview) - [Architecture Design Goals](#architecture-design-goals)
- [Architecture Design Goals](#architecture-design-goals) - [Components](#components)
- [Components](#components) - [L1 Components](#l1-components)
- [L1 Components](#l1-components) - [L2 Components](#l2-components)
- [L2 Components](#l2-components) - [Transaction/Block Propagation](#transactionblock-propagation)
- [Transaction/Block Propagation](#transactionblock-propagation) - [Key Interactions In Depth](#key-interactions-in-depth)
- [Key Interactions In Depth](#key-interactions-in-depth) - [Deposits](#deposits)
- [Deposits](#deposits) - [Block Derivation](#block-derivation)
- [Block Derivation](#block-derivation) - [Overview](#overview)
- [Overview](#overview) - [Epochs and the Sequencing Window](#epochs-and-the-sequencing-window)
- [Epochs and the Sequencing Window](#epochs-and-the-sequencing-window) - [Block Derivation Loop](#block-derivation-loop)
- [Block Derivation Loop](#block-derivation-loop) - [Engine API](#engine-api)
- [Engine API](#engine-api)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -4,21 +4,20 @@ ...@@ -4,21 +4,20 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Predeploys](#predeploys) - [Overview](#overview)
- [Overview](#overview) - [OVM\_L2ToL1MessagePasser](#ovm%5C_l2tol1messagepasser)
- [OVM\_L2ToL1MessagePasser](#ovm_l2tol1messagepasser) - [OVM\_DeployerWhitelist](#ovm%5C_deployerwhitelist)
- [OVM\_DeployerWhitelist](#ovm_deployerwhitelist) - [OVM\_ETH](#ovm%5C_eth)
- [OVM\_ETH](#ovm_eth) - [WETH9](#weth9)
- [WETH9](#weth9) - [L2CrossDomainMessenger](#l2crossdomainmessenger)
- [L2CrossDomainMessenger](#l2crossdomainmessenger) - [L2StandardBridge](#l2standardbridge)
- [L2StandardBridge](#l2standardbridge) - [SequencerFeeVault](#sequencerfeevault)
- [SequencerFeeVault](#sequencerfeevault) - [OptimismMintableERC20Factory](#optimismmintableerc20factory)
- [OptimismMintableERC20Factory](#OptimismMintableERC20Factory) - [L1BlockNumber](#l1blocknumber)
- [L1BlockNumber](#l1blocknumber) - [OVM\_GasPriceOracle](#ovm%5C_gaspriceoracle)
- [OVM\_GasPriceOracle](#ovm_gaspriceoracle) - [Reserved System Address 1](#reserved-system-address-1)
- [Reserved System Address 1](#reserved-system-address-1) - [Reserved System Address 2](#reserved-system-address-2)
- [Reserved System Address 2](#reserved-system-address-2) - [L1Block](#l1block)
- [L1Block](#l1block)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -9,14 +9,13 @@ ...@@ -9,14 +9,13 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [L2 Output Root Proposals Specification](#l2-output-root-proposals-specification) - [Proposing L2 Output Commitments](#proposing-l2-output-commitments)
- [Proposing L2 Output Commitments](#proposing-l2-output-commitments) - [L2 Output Commitment Construction](#l2-output-commitment-construction)
- [L2 Output Commitment Construction](#l2-output-commitment-construction) - [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract)
- [L2 Output Oracle Smart Contract](#l2-output-oracle-smart-contract) - [Security Considerations](#security-considerations)
- [Security Considerations](#security-considerations) - [L1 Reorgs](#l1-reorgs)
- [L1 Reorgs](#l1-reorgs) - [Summary of Definitions](#summary-of-definitions)
- [Summary of Definitions](#summary-of-definitions) - [Constants](#constants)
- [Constants](#constants)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -29,35 +29,34 @@ and are adopted by several other blockchains, most notably the [L1 consensus lay ...@@ -29,35 +29,34 @@ and are adopted by several other blockchains, most notably the [L1 consensus lay
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Rollup-node P2P interface](#rollup-node-p2p-interface) - [P2P configuration](#p2p-configuration)
- [P2P configuration](#p2p-configuration) - [Identification](#identification)
- [Identification](#identification) - [Discv5](#discv5)
- [Discv5](#discv5) - [Structure](#structure)
- [Structure](#structure) - [LibP2P](#libp2p)
- [LibP2P](#libp2p) - [Transport](#transport)
- [Transport](#transport) - [Dialing](#dialing)
- [Dialing](#dialing) - [NAT](#nat)
- [NAT](#nat) - [Peer management](#peer-management)
- [Peer management](#peer-management) - [Transport security](#transport-security)
- [Transport security](#transport-security) - [Protocol negotiation](#protocol-negotiation)
- [Protocol negotiation](#protocol-negotiation) - [Identify](#identify)
- [Identify](#identify) - [Ping](#ping)
- [Ping](#ping) - [Multiplexing](#multiplexing)
- [Multiplexing](#multiplexing) - [GossipSub](#gossipsub)
- [GossipSub](#gossipsub) - [Content-based message identification](#content-based-message-identification)
- [Content-based message identification](#content-based-message-identification) - [Message compression and limits](#message-compression-and-limits)
- [Message compression and limits](#message-compression-and-limits) - [Message ID computation](#message-id-computation)
- [Message ID computation](#message-id-computation) - [Heartbeat and parameters](#heartbeat-and-parameters)
- [Heartbeat and parameters](#heartbeat-and-parameters) - [Topic configuration](#topic-configuration)
- [Topic configuration](#topic-configuration) - [Topic validation](#topic-validation)
- [Topic validation](#topic-validation) - [Gossip Topics](#gossip-topics)
- [Gossip Topics](#gossip-topics) - [`blocks`](#blocks)
- [`blocks`](#blocks) - [Block encoding](#block-encoding)
- [Block encoding](#block-encoding) - [Block signatures](#block-signatures)
- [Block signatures](#block-signatures) - [Block validation](#block-validation)
- [Block validation](#block-validation) - [Block processing](#block-processing)
- [Block processing](#block-processing) - [Block topic scoring parameters](#block-topic-scoring-parameters)
- [Block topic scoring parameters](#block-topic-scoring-parameters)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
...@@ -8,34 +8,10 @@ ...@@ -8,34 +8,10 @@
[g-exec-engine]: glossary.md#execution-engine [g-exec-engine]: glossary.md#execution-engine
[g-reorg]: glossary.md#re-organization [g-reorg]: glossary.md#re-organization
[g-rollup-driver]: glossary.md#rollup-driver [g-rollup-driver]: glossary.md#rollup-driver
[g-inception]: glossary.md#L2-chain-inception
[g-receipts]: glossary.md#receipt [g-receipts]: glossary.md#receipt
[g-deposit-contract]: glossary.md#deposit-contract
[g-deposits]: glossary.md#deposits
[g-deposited]: glossary.md#deposited-transaction
[g-l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction
[g-user-deposited]: glossary.md#user-deposited-transaction
[g-l1-attr-predeploy]: glossary.md#l1-attributes-predeployed-contract
[g-depositing-call]: glossary.md#depositing-call
[g-depositing-transaction]: glossary.md#depositing-transaction
[g-mpt]: glossary.md#merkle-patricia-trie
[g-sequencing-window]: glossary.md#sequencing-window
[g-sequencing]: glossary.md#sequencing
[g-sequencer-batch]: glossary.md#sequencer-batch
The [rollup node][g-rollup-node] is the component responsible for [deriving the L2 chain][g-derivation] from L1 blocks The [rollup node][g-rollup-node] is the component responsible for [deriving the L2 chain][g-derivation] from L1 blocks
(and their associated [receipts][g-receipts]). This process happens in three steps: (and their associated [receipts][g-receipts]).
1. Select a [sequencing window][g-sequencing-window] from the L1 chain, on top of the last L2 block:
a list of blocks, with transactions and associated receipts.
2. Read L1 information, deposits, and sequencing batches in order to generate [payload attributes][g-payload-attr]
(essentially [a block without output properties][g-block]).
3. Pass the payload attributes to the [execution engine][g-exec-engine], so that the L2 block (including [output block
properties][g-block]) may be computed.
While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The
L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the
L1 chain [re-organizes][g-reorg].
The part of the rollup node that derives the L2 chain is called the [rollup driver][g-rollup-driver]. This document is The part of the rollup node that derives the L2 chain is called the [rollup driver][g-rollup-driver]. This document is
currently only concerned with the specification of the rollup driver. currently only concerned with the specification of the rollup driver.
...@@ -44,313 +20,39 @@ currently only concerned with the specification of the rollup driver. ...@@ -44,313 +20,39 @@ currently only concerned with the specification of the rollup driver.
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Rollup Node Specification](#rollup-node-specification) - [Driver](#driver)
- [L2 Chain Derivation](#l2-chain-derivation) - [Derivation](#derivation)
- [From L1 Sequencing Window to L2 Payload Attributes](#from-l1-sequencing-window-to-l2-payload-attributes) - [L2 Output RPC method](#l2-output-rpc-method)
- [Reading L1 inputs](#reading-l1-inputs) - [Output Method API](#output-method-api)
- [Encoding the L1 Attributes Deposited Transaction](#encoding-the-l1-attributes-deposited-transaction) - [L2 Batch creation RPC method](#l2-batch-creation-rpc-method)
- [Encoding User-Deposited Transactions](#encoding-user-deposited-transactions)
- [Deriving all Payload Attributes of a sequencing window](#deriving-all-payload-attributes-of-a-sequencing-window)
- [Building individual Payload Attributes](#building-individual-payload-attributes)
- [From Payload Attributes to L2 Block](#from-payload-attributes-to-l2-block)
- [Inductive Derivation Step](#inductive-derivation-step)
- [Engine API Error Handling](#engine-api-error-handling)
- [Finalization Guarantees](#finalization-guarantees)
- [Whole L2 Chain Derivation](#whole-l2-chain-derivation)
- [L2 Output RPC method](#l2-output-rpc-method)
- [Output Method API](#output-method-api)
- [Handling L1 Re-Orgs](#handling-l1-re-orgs)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
# L2 Chain Derivation ## Driver
[l2-chain-derivation]: #l2-chain-derivation
This section specifies how the [rollup driver][g-rollup-driver] derives a sequence of L2 blocks per sequencing window.
Every L2 block carries transactions of two categories:
- *[deposited transactions][g-deposited]*: two kinds:
- derived from the L1 chain: a single *[L1 attributes deposited transaction][g-l1-attr-deposit]* (always first).
- derived from [receipts][g-receipts]: zero or more *[user-deposited transactions][g-user-deposited]*.
- *[sequenced transactions][g-sequencing]*: derived from [sequencer batches][g-sequencer-batch],
zero or more regular transactions, signed by L2 users.
------------------------------------------------------------------------------------------------------------------------
## From L1 Sequencing Window to L2 Payload Attributes
A [sequencing window][g-sequencing-window] is a fixed number consecutive L1 blocks that a derivation step takes as
input. The window is identified by an `epoch`, equal to the block number of the first block in the window.
The derivation of the L2 chain from the L1 chain happens in steps.
Each step adds a variable number of L2 blocks to the L2 chain, derived from the sequencing window for the given epoch.
For epoch `N`, the sequencing window comprises L1 blocks `[N, N + SEQUENCING_WINDOW_SIZE)`.
Note that the sequencing windows overlap.
### Reading L1 inputs
The rollup reads the following data from the [sequencing window][g-sequencing-window]:
- Of the *first* block in the window only:
- L1 block attributes:
- block number
- timestamp
- basefee
- *random* (the output of the [`RANDOM` opcode][random])
- L1 log entries emitted for [user deposits][g-deposits], augmented with a [sourceHash](./deposits.md#).
- Of each block in the window:
- Sequencer batches, derived from the transactions:
- The transaction receiver is the sequencer inbox address
- The transaction must be signed by a recognized sequencer account
- The calldata may contain a bundle of batches. *(calldata will be substituted with blob data in the future.)*
- Batches not matching filter criteria are ignored:
- `batch.epoch == sequencing_window.epoch`, i.e. for this sequencing window
- `(batch.timestamp - genesis_l2_timestamp) % block_time == 0`, i.e. timestamp is aligned
- `min_l2_timestamp <= batch.timestamp < max_l2_timestamp`, i.e. timestamp is within range
- `min_l2_timestamp = prev_l2_timestamp + l2_block_time`
- `prev_l2_timestamp` is the timestamp of the previous L2 block: the last block of the previous epoch,
or the L2 genesis block timestamp if there is no previous epoch.
- `l2_block_time` is a configurable parameter of the time between L2 blocks
- `max_l2_timestamp = max(l1_timestamp + max_sequencer_drift, min_l2_timestamp + l2_block_time)`
- `l1_timestamp` is the timestamp of the L1 block associated with the L2 block's epoch
- `max_sequencer_drift` is the most a sequencer is allowed to get ahead of L1
- The batch is the first batch with `batch.timestamp` in this sequencing window,
i.e. one batch per L2 block number.
- The batch only contains sequenced transactions, i.e. it must NOT contain any Deposit-type transactions.
Note that after the above filtering `min_l2_timestamp >= l1_timestamp` always holds,
i.e. a L2 block timestamp is always equal or ahead of the timestamp of the corresponding L1 origin block.
[random]: https://eips.ethereum.org/EIPS/eip-4399
A bundle of batches is versioned by prefixing with a bundle version byte: `bundle = bundle_version ++ bundle_data`.
Bundle versions:
- `0`: `bundle_data = RLP([batch_0, batch_1, ..., batch_N])`
- `1`: `bundle_data = compress(RLP([batch_0, batch_1, ..., batch_N]))` (compression algorithm TBD)
A batch is also versioned by prefixing with a version byte: `batch = batch_version ++ batch_data`
and encoded as a byte-string (including version prefix byte) in the bundle RLP list.
Batch versions:
- `0`: `batch_data = RLP([epoch, timestamp, transaction_list])`, where each
Batch contents:
- `epoch` is the sequencing window epoch, i.e. the first L1 block number
- `timestamp` is the L2 timestamp of the block
- `transaction_list` is an RLP encoded list of [EIP-2718] encoded transactions.
[EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718
The L1 attributes are read from the L1 block header, while deposits are read from the block's [receipts][g-receipts].
Refer to the [**deposit contract specification**][deposit-contract-spec] for details on how deposits are encoded as log
entries. The deposited and sequenced transactions are combined when the Payload Attributes are constructed.
[deposit-contract-spec]: deposits.md#deposit-contract
### Encoding the L1 Attributes Deposited Transaction
The [L1 attributes deposited transaction][g-l1-attr-deposit] is a call that submits the L1 block attributes (listed
above) to the [L1 attributes predeployed contract][g-l1-attr-predeploy].
To encode the L1 attributes deposited transaction, refer to the following sections of the deposits spec:
- [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type)
- [L1 Attributes Deposited Transaction](deposits.md#l1-attributes-deposited-transaction)
### Encoding User-Deposited Transactions
A [user-deposited-transactions][g-deposited] is an L2 transaction derived from a [user deposit][g-deposits] submitted on
L1 to the [deposit contract][g-deposit-contract]. Refer to the [deposit contract specification][deposit-contract-spec]
for more details.
The user-deposited transaction is derived from the log entry emitted by the [depositing call][g-depositing-call], which
is stored in the [depositing transaction][g-depositing-transaction]'s log receipt.
To encode user-deposited transactions, refer to the following sections of the deposits spec:
- [The Deposited Transaction Type](deposits.md#the-deposited-transaction-type)
- [User-Deposited Transactions](deposits.md#user-deposited-transactions)
### Deriving all Payload Attributes of a sequencing window
A sequencing window is derived into a variable number of L2 blocks, defined by a range of timestamps:
- Starting at `min_l2_timestamp`, as defined in the batch filtering.
- Up to and including (including only if aligned with L2 block time)
`new_head_l2_timestamp = max(highest_valid_batch_timestamp, next_l1_timestamp - 1, min_l2_timestamp)`
- `highest_valid_batch_timestamp = max(batch.timestamp for batch in filtered_batches)`,
or `0` if no there are no `filtered_batches`.
`batch.timestamp` refers to the L2 block timestamp encoded in the batch.
- `next_l1_timestamp` is the timestamp of the next L1 block.
The L2 chain is extended to `new_head_l2_timestamp` with blocks at a fixed block time (`l2_block_time`).
This means that every `l2_block_time` that has no batch is interpreted as one with no sequenced transactions.
Each of the derived `PayloadAttributes` starts with a L1 Attributes transaction.
Like other derived deposits, this does not have to be batch-submitted, and exposes the required L1 information for the
process of finding the sync starting point of the L2 chain, without requiring L2 state access.
The [User-deposited] transactions are all put in the first of the derived `PayloadAttributes`,
inserted after the L1 Attributes transaction, before any [sequenced][g-sequencing] transactions.
#### Building individual Payload Attributes
[payload attributes]: #building-individual-payload-attributes
From the timestamped transaction lists derived from the sequencing window, the rollup node constructs [payload
attributes][g-payload-attr] as an [expanded version][expanded-payload] of the [`PayloadAttributesV1`] object, which
includes the additional `transactions` and `noTxPool` fields.
Each of the timestamped transaction lists translates to a `PayloadAttributesV1` as follows:
- `timestamp` is set to the timestamp of the transaction list.
- `random` is set to the *random* `execution_payload.prev_randao` L1 block attribute
- `suggestedFeeRecipient` is set to an address determined by the system
- `transactions` is the array of the derived transactions: deposited transactions and sequenced transactions.
All encoded with [EIP-2718].
- `noTxPool` is set to `true`, to use the exact above `transactions` list when constructing the block.
[expanded-payload]: exec-engine.md#extended-payloadattributesv1
[`PayloadAttributesV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#payloadattributesv1
------------------------------------------------------------------------------------------------------------------------ The task of the [driver][g-rollup-driver] in the [rollup node][g-rollup-node]
is to manage the [derivation][g-derivation] process:
## From Payload Attributes to L2 Block - Keep track of L1 head block
- Keep track of the L2 chain sync progress
- Iterate over the derivation steps as new inputs become available
Once the [payload attributes] for a given L1 block `B` have been built, and if we have already derived an L2 block from ### Derivation
`B`'s parent block, then we can use the payload attributes to derive a new L2 block.
### Inductive Derivation Step This process happens in three steps:
Let 1. Select inputs from the L1 chain, on top of the last L2 block:
a list of blocks, with transactions and associated data and receipts.
- `refL2` be the (hash of) the current L2 chain head 2. Read L1 information, deposits, and sequencing batches in order to generate [payload attributes][g-payload-attr]
- `refL1` be the (hash of) the L1 block from which `refL2` was derived (essentially [a block without output properties][g-block]).
- `payloadAttributes` be some previously derived [payload attributes] for the L1 block with number `l1Number(refL1) + 1` 3. Pass the payload attributes to the [execution engine][g-exec-engine], so that the L2 block (including [output block
properties][g-block]) may be computed.
Then we can apply the following pseudocode logic to update the state of both the rollup driver and execution engine:
```javascript
// request a new execution payload
forkChoiceState = {
headBlockHash: refL2,
safeBlockHash: refL2,
finalizedBlockHash: l2BlockHashAt(l2Number(refL2) - FINALIZATION_DELAY_BLOCKS)
}
[status, payloadID] = engine_forkchoiceUpdatedV1(forkChoiceState, payloadAttributes)
if (status != "SUCCESS") error()
// retrieve and execute the execution payload
[executionPayload, error] = engine_getPayloadV1(payloadID)
if (error != null) error()
[status, latestValidHash, validationError] = engine_newPayloadV1(executionPayload)
if (status != "VALID" || validationError != null) error()
refL2 = latestValidHash
refL1 = l1HashForNumber(l1Number(refL1) + 1))
// update head to new refL2
forkChoiceState = {
headBlockHash: refL2,
safeBlockHash: refL2,
finalizedBlockHash: l2BlockHashAt(l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS)
}
[status, payloadID] = engine_forkchoiceUpdatedV1(refL2, null)
if (status != "SUCCESS") error()
```
The following JSON-RPC methods are part of the [execution engine API][exec-engine]:
> **TODO** fortify the execution engine spec with more information regarding JSON-RPC, notably covering
> information found [here][json-rpc-info-1] and [here][json-rpc-info-2]
[json-rpc-info-1]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#from-l1-blocks-to-payload-attributes
[json-rpc-info-2]: https://github.com/ethereum-optimism/optimistic-specs/blob/a3ffa9a8c825d155a0469659b3101db5f41eecc4/specs/rollup-node.md#building-the-l2-block-with-the-execution-engine
[exec-engine]: exec-engine.md
- [`engine_forkchoiceUpdatedV1`] — updates the forkchoice (i.e. the chain head) to `headBlockHash` if different, and
instructs the engine to start building an execution payload given payload attributes the second argument isn't `null`
- [`engine_getPayloadV1`] — retrieves a previously requested execution payload
- [`engine_newPayloadV1`] — executes an execution payload to create a block
[`engine_forkchoiceUpdatedV1`]: exec-engine.md#engine_forkchoiceUpdatedV1
[`engine_getPayloadV1`]: exec-engine.md#engine_newPayloadV1
[`engine_newPayloadV1`]: exec-engine.md#engine_newPayloadV1
The execution payload is an object of type [`ExecutionPayloadV1`].
[`ExecutionPayloadV1`]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1
Within the `forkChoiceState` object, the properties have the following meaning:
- `headBlockHash`: block hash of the last block of the L2 chain, according to the rollup driver.
- `safeBlockHash`: same as `headBlockHash`.
- `finalizedBlockHash`: the hash of the block whose number is `l2Number(headBlockHash) - FINALIZATION_DELAY_BLOCKS` if
the number of that block is `>= L2_CHAIN_INCEPTION`, 0 otherwise (\*) See the [Finalization Guarantees][finalization]
section for more details.
(\*) where:
- `FINALIZATION_DELAY_BLOCKS == 50400` (approximately 7 days worth of L1 blocks)
- `L2_CHAIN_INCEPTION` is the [L2 chain inception][g-inception] (the number of the first L1 block for which an L2 block
was produced).
Finally, the `error()` function signals an error that must be handled by the implementation. Refer to the next section
for more details.
### Engine API Error Handling
[error-handling]: #engine-api-error-handling
All invocations of [`engine_forkchoiceUpdatedV1`], [`engine_getPayloadV1`] and [`engine_newPayloadV1`] by the
rollup driver should not result in errors assuming conformity with the specification. Said otherwise, all errors are
implementation concerns and it is up to them to handle them (e.g. by retrying, or by stopping the chain derivation and
requiring manual user intervention).
The following scenarios are assimilated to errors:
- [`engine_forkchoiceUpdatedV1`] returning a `status` of `"SYNCING"` instead of `"SUCCESS"` whenever passed a
`headBlockHash` that it retrieved from a previous call to [`engine_newPayloadV1`].
- [`engine_newPayloadV1`] returning a `status` of `"SYNCING"` or `"INVALID"` whenever passed an execution payload
that was obtained by a previous call to [`engine_getPayloadV1`].
### Finalization Guarantees
[finalization]: #finalization-guarantees
As stated earlier, an L2 block is considered *finalized* after a delay of `FINALIZATION_DELAY_BLOCKS == 50400` L1 blocks
after the L1 block that generated it. This is a duration of approximately 7 days worth of L1 blocks. This is also known
as the "fault proof window", as after this time the block can no longer be challenged by a fault proof.
L1 Ethereum reaches [finality][l1-finality] approximately every [12.8 minutes][consensus-time-params]. L2 blocks
generated from finalized L1 blocks are "safer" than most recent L2 blocks because they will never disappear from the
chain's history because of a re-org. However, they can still be challenged by a fault proof until the end of the fault
proof window.
[l1-finality]: https://www.paradigm.xyz/2021/07/ethereum-reorgs-after-the-merge
[consensus-time-params]: https://github.com/ethereum/consensus-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#time-parameters
> **TODO** the spec doesn't encode the notion of fault proof yet, revisit this (and include links) when it does
## Whole L2 Chain Derivation
The [block derivation](#from-l1-blocks-to-payload-attributes) presents an inductive process:
given that we know the last L2 block derived from the previous [sequencing window][g-sequencing-window], as well as the
next [sequencing window][g-sequencing-window], then we can derive [payload attributes] of the next L2 blocks.
To derive the whole L2 chain from scratch, we simply start with the L2 genesis block as the last L2 block, and the While this process is conceptually a pure function from the L1 chain to the L2 chain, it is in practice incremental. The
block at height `L2_CHAIN_INCEPTION + 1` as the start of the next sequencing window. L2 chain is extended whenever new L1 blocks are added to the L1 chain. Similarly, the L2 chain re-organizes whenever the
Then we iteratively apply the derivation process from the previous section by shifting the sequencing window one L1 L1 chain [re-organizes][g-reorg].
block forward each step, until there is an insufficient number of L1 blocks left for a complete sequencing window.
> **TODO** specify genesis block For a complete specification of the L2 block derivation, refer to the [L2 block derivation document](./derivation.md).
## L2 Output RPC method ## L2 Output RPC method
...@@ -373,62 +75,6 @@ The input and return types here are as defined by the [engine API specs][engine- ...@@ -373,62 +75,6 @@ The input and return types here are as defined by the [engine API specs][engine-
1. `version`: `DATA`, 32 Bytes - the output root version number, beginning with 0. 1. `version`: `DATA`, 32 Bytes - the output root version number, beginning with 0.
1. `l2OutputRoot`: `DATA`, 32 Bytes - the output root 1. `l2OutputRoot`: `DATA`, 32 Bytes - the output root
# Handling L1 Re-Orgs ## L2 Batch creation RPC method
[l1-reorgs]: #handling-L1-re-orgs
The [previous section on L2 chain derivation][l2-chain-derivation] assumes linear progression of the L1 chain. It is
also applicable for batch processing, meaning that any given point in time, the canonical L2 chain is given by
processing the whole L1 chain since the [L2 chain inception][g-inception].
If the L1 Chain re-orgs, the rollup node must re-derive sections of the L2 chain such that it derives the same L2 chain
that a rollup node would derive if it only followed the new L1 chain.
> By itself, the previous section fully specifies the behavior of the rollup driver. **The current section is
> non-specificative** but shows how L1 re-orgs can be handled in practice.
In practice, the L1 chain is processed incrementally. However, the L1 chain may occasionally [re-organize][g-reorg],
meaning the head of the L1 chain changes to a block that is not the child of the previous head but rather another
descendant of an ancestor of the previous head. In that case, the rollup driver must first search for the common L1
ancestor, and can re-derive the L2 chain from that L1 block and onward.
The rollup node maintains two heads of the L2 Chain: the unsafe head (often called head) and the safe head.
Each L2 block has an L1 origin block (corresponding to its epoch) that it references in the
[L1 attributes deposited transaction][l1-attr-deposit]. The unsafe head is the head of the L2 chain.
Its L1 origin block should be canonical or potentially extending the canonical chain
(if the rollup node has not yet seen the L1 block that it is based upon).
The safe head is the the last L2 block of the last epoch whose sequencing window is complete
(i.e. the epoch with number `L1Head.number` - `SEQUENCING_WINDOW_SIZE`).
[l1-attr-deposit]: glossary.md#l1-attributes-deposited-transaction
Steps during a reorg:
1. Set "unsafe head" to equal the l2 head we retrieved, just as default
2. Set "latest block" to equal the l2 head we retrieved, also just as default
3. Walk back L2, and stop until block.l1Origin is found AND canonical, and update "latest block" to this block.
And don't override "unsafe head" if it's not found, but do override it when block.l1Origin does not match the
canonical L1 block at that height.
4. Walk back L2 from the "latest block" until a full sequencing window of L1 blocks has been passed.
This is the "safe block".
The purpose of this is to ensure that if the sequencing window for a L2 block has changed since it was derived,
that L2 block is re-derived.
The first L1 block of the sequencing window is the L1 attributes for that L2 block. The end of the sequencing
window is the canonical L1 block whose number is `SEQUENCING_WINDOW` larger than the start. The end of the
window must be selected by number otherwise the sequencer would not be able to create batches. The problem
with selecting the end of the window by number is that when an L1 reorg occurs, the blocks (and thus batches)
in the window could change. We must find the find the first L2 block whose complete sequencing window is
unchanged in the reorg.
When walking back on the L2 chain, care should be taken to not walk past the rollup genesis.
Note that post-[merge], the depth of re-orgs will be bounded by the [L1 finality delay][l1-finality] (every 2 epochs,
approximately 12 minutes).
(\*) Post-merge, this is only possible for 12 minutes. In practice, we'll pick an already-finalized L1 block as L2
inception point to preclude the possibility of a re-org past genesis, at the cost of a few empty blocks at the start of
the L2 chain.
[merge]: https://ethereum.org/en/eth2/merge/ See [Batch derivation](./batching.md) for an RPC specification for batch data submission.
...@@ -33,19 +33,18 @@ finalization. ...@@ -33,19 +33,18 @@ finalization.
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents** **Table of Contents**
- [Withdrawals](#withdrawals) - [Withdrawal Flow](#withdrawal-flow)
- [Withdrawal Flow](#withdrawal-flow) - [On L2](#on-l2)
- [On L2](#on-l2) - [On L1](#on-l1)
- [On L1](#on-l1) - [The L2ToL1MessagePasser Contract](#the-l2tol1messagepasser-contract)
- [The L2ToL1MessagePasser Contract](#the-l2tol1messagepasser-contract) - [Addresses are not Aliased on Withdrawals](#addresses-are-not-aliased-on-withdrawals)
- [Addresses are not Aliased on Withdrawals](#addresses-are-not-aliased-on-withdrawals) - [The Optimism Portal Contract](#the-optimism-portal-contract)
- [The Optimism Portal Contract](#the-optimism-portal-contract) - [Withdrawal Verification and Finalization](#withdrawal-verification-and-finalization)
- [Withdrawal Verification and Finalization](#withdrawal-verification-and-finalization) - [Security Considerations](#security-considerations)
- [Security Considerations](#security-considerations) - [Key Properties of Withdrawal Verification](#key-properties-of-withdrawal-verification)
- [Key Properties of Withdrawal Verification](#key-properties-of-withdrawal-verification) - [Handling Successfully Verified Messages That Fail When Relayed](#handling-successfully-verified-messages-that-fail-when-relayed)
- [Handling Successfully Verified Messages That Fail When Relayed](#handling-successfully-verified-messages-that-fail-when-relayed) - [Summary of Definitions](#summary-of-definitions)
- [Summary of Definitions](#summary-of-definitions) - [Constants](#constants)
- [Constants](#constants)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment