1"use strict";(self.webpackChunkl_2_o_docs=self.webpackChunkl_2_o_docs||[]).push([[939],{7173:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>c,contentTitle:()=>r,default:()=>a,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var i=n(5893),t=n(1151);const s={},r="Submit L2 Block",l={id:"l2o-a/operations/block",title:"Submit L2 Block",description:'The "block" operation submits the result + proof of a new block for a Layer 2 blockchain deployed on Bitcoin.',source:"@site/docs/l2o-a/operations/block.mdx",sourceDirName:"l2o-a/operations",slug:"/l2o-a/operations/block",permalink:"/docs/l2o-a/operations/block",draft:!1,unlisted:!1,editUrl:"https://github.com/L2Ordinals/docs/tree/main/packages/create-docusaurus/templates/shared/docs/l2o-a/operations/block.mdx",tags:[],version:"current",frontMatter:{},sidebar:"docs",previous:{title:"Operations",permalink:"/docs/category/operations"},next:{title:"Deploy Layer 2",permalink:"/docs/l2o-a/operations/deploy"}},c={},d=[{value:"Parameters",id:"parameters",level:2},{value:"Block Verification Logic",id:"block-verification-logic",level:2},{value:"Pseudo Schema",id:"pseudo-schema",level:2}];function h(e){const o={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.a)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(o.h1,{id:"submit-l2-block",children:"Submit L2 Block"}),"\n",(0,i.jsx)(o.p,{children:'The "block" operation submits the result + proof of a new block for a Layer 2 blockchain deployed on Bitcoin.'}),"\n",(0,i.jsx)(o.h2,{id:"parameters",children:"Parameters"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"p"}),': "l2o-a" (The ordinal protocol, which is ',(0,i.jsx)(o.code,{children:'"l2o-a"'}),")"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"op"}),': "Block" (The operation id, which is "Block")']}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"l2id"}),": A unique unsigned 32bit number that identifies the layer 2 which has already been ",(0,i.jsx)(o.a,{href:"./deploy",children:"deployed"}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsxs)(o.li,{children:["Note: The l2id ",(0,i.jsx)(o.code,{children:"0"})," is reserved for representing the Bitcoin Layer 1 blockchain"]}),"\n",(0,i.jsxs)(o.li,{children:["Note: ",(0,i.jsx)(o.em,{children:"if an incoming block operation specifies an l2id which has not been deployed, then the incoming block operation is NOOP"})]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"bitcoin_block_number"}),": The bitcoin block number which the L2 is currently synced to (must be greater than the previous block proof)"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"bitcoin_block_hash"}),": The ",(0,i.jsx)(o.a,{href:"https://en.bitcoin.it/wiki/Block_hashing_algorithm",children:"block hash"})," of the Bitcoin block at height ",(0,i.jsx)(o.code,{children:"bitcoin_block_number"})]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"l2_block_number"}),": The current block number of the L2 (must be 1 more than the previous block proof)"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"public_key"}),": The public key which is used to verify the next block proof's signature","\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsxs)(o.li,{children:["Note: if public_key is set to the empty string ",(0,i.jsx)(o.code,{children:'""'})," or ",(0,i.jsx)(o.code,{children:'"0"'})," then the next block proof's signature is ignored"]}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"start_state_root"}),": The state root of the L2 before the incoming L2 block was executed (the previous L2 block's ",(0,i.jsx)(o.code,{children:"end_state_root"}),")"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"end_state_root"}),": The state root of the L2 after the incoming L2 block was executed"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"deposit_state_root"}),": The Merkle Root of L2's BRC-21 deposit tree as of the bitcoin block specified by ",(0,i.jsx)(o.code,{children:"bitcoin_block_number"})]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"start_withdrawal_state_root"}),": The Merkle Root of L2's BRC-21 withdrawal tree at the start L2 block specified by ",(0,i.jsx)(o.code,{children:"l2_block_number"})]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"end_withdrawal_state_root"}),": The Merkle Root of L2's BRC-21 withdrawal tree at the end L2 block specified by ",(0,i.jsx)(o.code,{children:"l2_block_number"})]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"superchain_root"}),": The Merkle Root of the ",(0,i.jsx)(o.a,{href:"../superchain",children:"Superchain"})," merkle state tree hashed with the ",(0,i.jsx)(o.code,{children:"hash_function"})," configured when the L2 was deployed at block ",(0,i.jsx)(o.code,{children:"bitcoin_block_number"})]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"proof"}),": A zero knowledge proof of the L2's block with a single public input which is the hash (using to the ",(0,i.jsx)(o.code,{children:"hash_function"})," configured when the L2 was deployed) of the following parameters concatenated:","\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"l2_block_number"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"bitcoin_block_hash"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"public_key"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"start_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"end_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"deposit_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"start_withdrawal_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"end_withdrawal_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"superchain_root"})}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(o.li,{children:[(0,i.jsx)(o.code,{children:"signature"}),": A schnorr signature of the sha256 hash of the proof, checked against the previous block proofs public key","\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:'if the previous block proof\'s public key was "0" or an empty string, the signature is ignored'}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(o.h2,{id:"block-verification-logic",children:"Block Verification Logic"}),"\n",(0,i.jsxs)(o.ol,{children:["\n",(0,i.jsx)(o.li,{children:"Check if the L2 ID is deployed/valid (if the id is invali
1d or does not exist, the operation is a NOOP)"}),"\n",(0,i.jsx)(o.li,{children:"Fetch the following parameters from the L2's deployment configuration:"}),"\n"]}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"last_l2_block_number"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"last_bitcoin_block_number"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"last_end_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"last_end_withdrawal_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"last_public_key"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"proof_type"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"hash_function"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"verifier_data"})}),"\n"]}),"\n",(0,i.jsxs)(o.ol,{start:"3",children:["\n",(0,i.jsxs)(o.li,{children:["Validate the JSON payload, ensuring to range check the inputs based on the ",(0,i.jsx)(o.code,{children:"proof_type"}),"'s field"]}),"\n",(0,i.jsxs)(o.li,{children:["Ensure that ",(0,i.jsx)(o.code,{children:"l2_block_number == (last_l2_block_number + 1)"})]}),"\n",(0,i.jsxs)(o.li,{children:["Ensure that ",(0,i.jsx)(o.code,{children:"bitcoin_block_number > last_bitcoin_block_number"})]}),"\n",(0,i.jsxs)(o.li,{children:["Ensure that ",(0,i.jsx)(o.code,{children:"start_state_root == last_end_state_root"})]}),"\n",(0,i.jsxs)(o.li,{children:["Ensure that ",(0,i.jsx)(o.code,{children:"start_withdrawal_state_root == last_end_withdrawal_state_root"})]}),"\n",(0,i.jsxs)(o.li,{children:["Compute the expected public input by hashing the following parameters using ",(0,i.jsx)(o.code,{children:"hash_function"})," and ensuring it equals the public input of the proof:"]}),"\n"]}),"\n",(0,i.jsxs)(o.ul,{children:["\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"l2_block_number"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"bitcoin_block_hash"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"public_key"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"start_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"end_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"deposit_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"start_withdrawal_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"end_withdrawal_state_root"})}),"\n",(0,i.jsx)(o.li,{children:(0,i.jsx)(o.code,{children:"superchain_root"})}),"\n"]}),"\n",(0,i.jsxs)(o.ol,{start:"9",children:["\n",(0,i.jsxs)(o.li,{children:["Fetch the block hash at ",(0,i.jsx)(o.code,{children:"bitcoin_block_number"})," and ensure it is equal to ",(0,i.jsx)(o.code,{children:"bitcoin_block_hash"})]}),"\n",(0,i.jsxs)(o.li,{children:["Fetch the BRC-21 deposit state root at block ",(0,i.jsx)(o.code,{children:"bitcoin_block_number"})," and ensure it equals ",(0,i.jsx)(o.code,{children:"deposit_state_root"})]}),"\n",(0,i.jsxs)(o.li,{children:["Fetch the super chain root of the super chain state merkle tree hashed with ",(0,i.jsx)(o.code,{children:"hash_function"})," at ",(0,i.jsx)(o.code,{children:"bitcoin_block_number"})," and ensure it equals ",(0,i.jsx)(o.code,{children:"superchain_root"})]}),"\n",(0,i.jsxs)(o.li,{children:["If the ",(0,i.jsx)(o.code,{children:"last_public_key"})," is not null or 0, hash the proof and check the signature"]}),"\n",(0,i.jsxs)(o.li,{children:["Verify the zero knowledge proof using ",(0,i.jsx)(o.code,{children:"verifier_data"})]}),"\n",(0,i.jsx)(o.li,{children:"Update the L2's database record (see psuedo-code below):"}),"\n"]}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-jsx",children:"l2_state.last_bitcoin_block_number = bitcoin_block_number;\nl2_state.last_l2_block_number = l2_block_number;\nl2_state.last_public_key = public_key;\nl2_state.last_end_state_root = end_state_root;\nl2_state.last_end_withdrawal_state_root = end_withdrawal_state_root;\n"})}),"\n",(0,i.jsxs)(o.ol,{start:"14",children:["\n",(0,i.jsxs)(o.li,{children:["Update the Superchain merkle tree leaf at index ",(0,i.jsx)(o.code,{children:"l2id"}),", setting the value of the leaf to ",(0,i.jsx)(o.code,{children:"last_end_state_root"})]}),"\n"]}),"\n",(0,i.jsx)(o.h2,{id:"pseudo-schema",children:"Pseudo Schema"}),"\n",(0,i.jsx)(o.pre,{children:(0,i.jsx)(o.code,{className:"language-jsx",children:'{\n "p": "l2o-a",\n "op": "Block",\n "l2id": 1, // replace with your l2 id\n "bitcoin_block_number": 999, //replace with your bitcoin block number\n "bitcoin_block_hash": "<bitcoin block hash at bitcoin_block_number>",\n "l2_block_number": 1337, // replace with your L2 blockchain\'s block number\n "public_key": "<the schnorr public key that must sign your next block proof, 0 if no signature is required>",\n "start_state_root": "<the start state root for your L2\'s block>",\n "end_state_root": "<the end state root for your L2\'s block>",\n "deposit_state_root": "<the root of the deposit tree for your L2 at block >",\n "start_withdrawal_state_root": "<proof type>",\n "end_withdrawal_state_root": "<proof type>",\n "proof": {\n "...": "<block zero knowledge proof for this L2 block>"\n },\n "superchain_root": "<super chain state merkle root>",\n "signature": "<schnorr signature of proof with public inputs>"\n}\n'})})]})}function a(e={}){const{wrapper:o}={...(0,t.a)(),...e.components};return o?(0,i.jsx)(o,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},1151:(e,o,n)=>{n.d(o,{Z:()=>l,a:()=>r});var i=n(7294);const t={},s=i.createContext(t);function r(e){const o=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function l(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(s.Provider,{value:o},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.