<100 subscribers

เทียบกันแบบชัดๆอัพเกรดใหม่ ใหญ่สะใจของ 2 ตัวตึงประจำ L2 @optimismFND Bedrock VS @arbitrum Nitro เทคของใครจะตอบโจทย์การใช้กว่า?
แปลจาก @norswap dev ของ OP ที่มีส่วนในการพัฒนา Bedrock และรีเสิร์ช Nitro ผ่าน Whitepaper ที่อาสามาอธิบายความเหมือนที่แตกต่างกันแบบเจาะลึก

➡️Nitro ดีไซน์ให้ทำงานเหมือน OP เวอชั่นปัจจุบัน ซึ่งตั้งค่าให้ 1 Block = 1 txn และ Block time = ผันแปร
➡️Bedrock จะเลิกใช้สิ่งนี้และปรับ Block time ให้ Fixed ที่ 2 วิ
Block time แบบผันแปลและไม่คงที่อาจทำให้ Contract มีอาการเอ๋อๆ เพราะ Contract พวกนี้จะถูกกำหนดเวลาจาก Block แทนที่จะเป็นจาก Timestamps ตย. Masterchef contract ของซูชิ ปัญหานี้เคยทำให้ Incentive บน Stargate (OP) หมดเกลี้ยงก่อนเชนอื่นเป็นเดือนๆ เพราะเวลาที่ไม่คงที่นี้แหละ
➡️Nitro ข้อเสียของ 1 Block = 1 txn
cost ต่อ Txn สูง
State root ต้องอัพเดทแยกกันในแต่ละTxn
➡️ Bedrock : Block จะถูกสร้างทุกๆ 2 วิ โดยไม่ Fix ว่าในบล็อกนั้นๆจะมี Txn ใส่ไปมั้ย
✨นึกภาพแท็กซี่ที่ต้องออกรถทุกๆ2 วิ กับแท็กซี่ที่ต้องรอผู้โดยสารขึ้นก่อนออกรถ แบบไหนจะเร็วกว่ากัน

➡️ Nitro ใช้ Geth เป็น library ซึ่งไม่ต้องปรับอะไรก็ทำงานได้ถูกต้อง
➡️ Bedrock ปรับ Geth ให้รันแบบ Standalone ในฐานะ Execution engine เพื่อรับ instructions จาก rollup node เหมือน Eth2 ที่ Exec layer รับ instructions จาก consensus layer เปี๊ยบ (พวกเค้าใช้APIตัวเดียวกันด้วยซ้ำ)
ไอเดียนี้ถือเป็นไฮไลต์ของ Bedrock ที่ทำให้สามารถใช้ Client ได้หลายๆ ตัว ซึ่งสิ่งนี้ไม่ใช่แค่ทฤษฏีเพราะตอนนี้ Erigon ก็พร้อมใช้งานแล้ว
อีกข้อดีคือสิ่งนี้จะช่วยทุ่นแรง Dev ได้มากเพราะสามารถรียูส Geth Stack หรือ Client ตัวอื่นๆ ได้ทั้งก้อน

➡️ Nitro บันทึกบาง State ("the state of ArbOS") ใน special account โดยใช้ special memory layout เพื่อแม็ป storage slots (เป็นเรื่องของ architecture ล้วนๆ user ไม่รู้สึก)
➡️ Bedrock แตกต่างเล็กน้อยโดยจะบันทึกลงใน EVM contracts ทั่วๆ ไป (จริงๆเรา implement ArbOs ด้วย EVMได้)
Bedrock เมื่อ Determine/executing block ถัดไปของ L2 จะดูที่ -Header ของ Headerของ L2 chain -อ่าน data จาก L1 -บาง dataใน EVM contract บน L2 chain บน Bedrock ถ้า Node ไหนล่มมันจะรีตัวเองทันทีโดยไม่ต้องเก็บฐานข้อมูลพิเศษเพราะอยู่ใน L1/L2 block ครบ - Nitro ก็น่าจะคล้ายกัน

Nitro ประมวลผลแมสเสจจาก L1-L2 (หรือที่เรียกว่า Deposit txn) ดีเลย์ที่ 10min
Bedrock ยืนยันโดยใช้ Block ประมาณนึง (ประมาณ2min) โดยมี parameter ชื่อ "sequencer drift" ที่สามารถทำ Timestamp L2 block ให้คล่อม L1 Block ได้ ถ้าหากเกิน 10min โดยไม่มี Deposit ก็จะถูกตีกลับ
➡️ Nitro ใน WPP อธิบายเรื่องดีเลย์ 10min เพื่อป้องกันการ Re-Org แต่ไม่มีอธิบายว่าแล้ว L2 จะรับมือกับการ Re-Org บน L1 ยังไง คนเขียนเดาว่าน่าจะไม่ทำอะไร ซึ่งก็ Work ในบางเคส
➡️ Bedrock จะรับมือกับการ Re-Org บน L1 ด้วยการ Re-Org บน L2 ถ้าจำเป็น

ถ้าคุณกำลังบริดจ์ โดย L1 ล็อกเหรียญเรียบร้อย แต่คำสั่งบน L2 เฟล คุณจะต้องสามารถเริ่มคำสั่งบน L2 ใหม่ได้ (อาจเสียแกสเพิ่ม) ไม่งั้นจะเสียเหรียญทั้งหมด
➡️ Nitro อิมพลิเมนต์เป็น "retryable tickets" สำหรับการส่ง Msg จาก L1-L2 โดยใช้ ArbOS
➡️ Bedrock ทำทั้งหมดนี้โดยใช้แค่ Solidity

L2 Fee ทั้งคู่ใช้ระบบเดียวกันโดยคิดจาก Exec Gas บน L2 + cost จาก L1 Calldata
➡️ Nitro ใช้ระบบใหม่โดยเฉพาะ ซึ่งคิดและออกแบบมาอย่างดี (Elegant) เพื่อให้ลงตัวกับ 1block/1txn
➡️ Bedrock รียูสจาก EIP-1559 ซึ่งทำงานได้ดีกับ Block Time 2 วิ และดีสำหรับการคำนวณของ Wallet/Tools

L1 Fee คิดต่างกัน
➡️ Bedrock คำนวณ L1 Fee โดยดูย้อนหลังที่ L1 basefee data ทำให้ได้ราคาค่อนข้างเรียลไทม์ (หลักการเดียวกับ Deposit) แต่เพราะ L1 Fee มีโอกาสพุ่งตลอดเวลาเลยต้องชาร์จ Multiplier เล็กน้อยของราคาที่คาด ค่า Multiplier ปัจจุบันถูกปรับลดจากตอนเริ่ม+จะลดลงอีกด้วย EIP4844
OP เลือกทางนี้เพราะจะทำให้สามารถเก็บ Fee จาก MEV ได้เพิ่ม เพื่อนำมาแจกจ่าย OP User ได้
➡️ Nitro คิดระบบที่ซับซ้อน โดยใช้ระบบควบคุมที่สามารถรับข้อมูลราคาที่ต้องจ่ายบน L1 แปลว่าถ้า Sequencer จ่ายน้อยก็คิดกับ User น้อย/จ่ายมากคิดมากขึ้น

Fault proof ต่างกัน
➡️ OP ใช้ Cannon (อิมพลิเมนต์ on Top Bedrock) และ Compile=MIPS
➡️ Nitro Compile=WASM ซึ่งเปลี่ยน output มากกว่า เรียกว่า WAVM โดยทั้งคู่แทนที่ floating point (FP) operations โดยใช้ library calls (Bedrock ใช้ GO ทำสิ่งนี้)

➡️ Bedrock fault proof รันโดยใช้ minigeth เพื่อยืนยันความถูกต้องของ state root และโพสต์บน L1 โดยใช้ Cannon ในการหา state root ที่เห็นแย้ง
➡️ Nitro โพสต์ state root เป็นก้อนๆ (RBlock) บน L1 เริ่มจากหา State root ที่ challenger/def เห็นไม่ตรงกันก่อนแล้วหา WAVM ที่เห็นไม่ตรงกันต่อ

Preimage Oracle validator software ถูกใช้สำหรับ Fault Proof ในการอ่าน L1/L2 data สุดท้ายแล้วมันจะรันที่ L1 (เข้าถึง L2 ก็ต้องเข้าผ่านL1) เราจะอ่านข้อมูล state/chain ยังไง? Merkle Root Node คือ hash ของลูกๆ เมื่อคุณรีเควส Preimage เพื่อดู state tree ก็จะเห็นทั้งหมด(พ่อ/ลูก)
เช่นเดียวกัน คุณสามารถหา Preimage ของทั้งเชนย้อนหลังโดยรีเควส preimage ของ block header (ในทุก Block Header จะมี Hash ย้อนไปถึง parent) เมื่อ Execute on-chain จะออกมาเป็น WAVM หรือ MIPS นี่คือวิธีการอ่านข้อมูล L2 ของทั้ง Nitro และ Bedrock
สำหรับ L1 ก็คล้ายกัน ต่างกันที่ก้อน Txn จะถูกเก็บใน L1 Calldata เข้าถึงผ่าน Smart Contract L1 ไม่ได้
➡️ Nitro เก็บ hashes ของทั้งก้อนใน L1 contract นี่คือเหตุผลที่ "Sequencer Inbox" เป็น Contract ต่างกับ Bedrock ที่เป็น EOA
➡️ Bedrock ไม่ต้องเก็บ Hash ใดๆ (ทำให้ประหยัดค่าแกสได้มากกว่า) แต่พวกเขาจะใช้ข้อมูลจาก Callata โดยเริ่มจากย้อนกลับไปใช้ L1 block headers และหา transaction Merkle root จะเจอก้อนข้อมูลใน calldata

➡️ Bedrock เจอสิ่ง "large preimage problem" เพราะต้อง Invert ให้ receipts preimage บางตัว ซึ่งในนั้นมี log data เรียงต่อกันยาวๆ ทำให้เสี่ยงถูกโจมตี ด้วยการอัด Log มหาศาลเพื่อสร้าง large preimage สิ่งนี้จะถูกแก้ด้วย zk-proof ในอนาคต (OPไม่เก็บ hash เพื่อลด cost การเก็บ+compute)
➡️ Nitro ใน WPP มีพูดเรื่องการแก้ L2 Preimage ขนาดใหญ่ที่ 110kb แต่ไม่มีพูดถึง L1

➡️ Nitroโยงก้อน Txn เข้ากับ State root อย่างแน่นหนา และโพสต์ชุดของข้อมูลใน RBlock ซึ่งมี State Root ด้วย
➡️ Bedrock โพสต์แต่ละก้อนแยกจากกันเพื่อลดค่าใช้จ่าย (ไม่ต้อง Interact กับ Contract หรือเก็บข้อมูลใดๆ) และโพสต์ก้อน Txn บ่อยขึ้นแต่โพสต์ State root น้อยลง
ชาเลนจ์ของ Nitro คือ RBlock ถูกชาเลนจ์ได้มั้ย? และ Txn ในนั้นจะไม่ Replayed บนเชนใหม่
ส่วนของ Bedrock ทางทีมยังคุยกันอยู่ว่าถ้า state root ถูกชาเลนจ์จะทำยังไง จะ Replay Txn เก่าบน State Root ใหม่มั้ย หรือจะ Rollback หมดเลย
จะเห็นว่าในความเหมือนของทั้งสองสิ่งนี้ มีดีเทลที่แตกต่างกันพอสมควร บางเรื่อง User อย่างเรารู้สึกได้ บางเรื่องก็ลึกระดับ Dev เท่านั้นที่เข้าใจ ขอบคุณที่อ่านมาถึงตรงนี้ สำหรับพาร์ทที่ Technical มากๆ จนต้องใช้ทับศัพย์และอาจแปลผิดหรือคลาดเคลื่อนไปบ้าง รบกวนแนะนำเพื่อปรับแก้ครับ

เทียบกันแบบชัดๆอัพเกรดใหม่ ใหญ่สะใจของ 2 ตัวตึงประจำ L2 @optimismFND Bedrock VS @arbitrum Nitro เทคของใครจะตอบโจทย์การใช้กว่า?
แปลจาก @norswap dev ของ OP ที่มีส่วนในการพัฒนา Bedrock และรีเสิร์ช Nitro ผ่าน Whitepaper ที่อาสามาอธิบายความเหมือนที่แตกต่างกันแบบเจาะลึก

➡️Nitro ดีไซน์ให้ทำงานเหมือน OP เวอชั่นปัจจุบัน ซึ่งตั้งค่าให้ 1 Block = 1 txn และ Block time = ผันแปร
➡️Bedrock จะเลิกใช้สิ่งนี้และปรับ Block time ให้ Fixed ที่ 2 วิ
Block time แบบผันแปลและไม่คงที่อาจทำให้ Contract มีอาการเอ๋อๆ เพราะ Contract พวกนี้จะถูกกำหนดเวลาจาก Block แทนที่จะเป็นจาก Timestamps ตย. Masterchef contract ของซูชิ ปัญหานี้เคยทำให้ Incentive บน Stargate (OP) หมดเกลี้ยงก่อนเชนอื่นเป็นเดือนๆ เพราะเวลาที่ไม่คงที่นี้แหละ
➡️Nitro ข้อเสียของ 1 Block = 1 txn
cost ต่อ Txn สูง
State root ต้องอัพเดทแยกกันในแต่ละTxn
➡️ Bedrock : Block จะถูกสร้างทุกๆ 2 วิ โดยไม่ Fix ว่าในบล็อกนั้นๆจะมี Txn ใส่ไปมั้ย
✨นึกภาพแท็กซี่ที่ต้องออกรถทุกๆ2 วิ กับแท็กซี่ที่ต้องรอผู้โดยสารขึ้นก่อนออกรถ แบบไหนจะเร็วกว่ากัน

➡️ Nitro ใช้ Geth เป็น library ซึ่งไม่ต้องปรับอะไรก็ทำงานได้ถูกต้อง
➡️ Bedrock ปรับ Geth ให้รันแบบ Standalone ในฐานะ Execution engine เพื่อรับ instructions จาก rollup node เหมือน Eth2 ที่ Exec layer รับ instructions จาก consensus layer เปี๊ยบ (พวกเค้าใช้APIตัวเดียวกันด้วยซ้ำ)
ไอเดียนี้ถือเป็นไฮไลต์ของ Bedrock ที่ทำให้สามารถใช้ Client ได้หลายๆ ตัว ซึ่งสิ่งนี้ไม่ใช่แค่ทฤษฏีเพราะตอนนี้ Erigon ก็พร้อมใช้งานแล้ว
อีกข้อดีคือสิ่งนี้จะช่วยทุ่นแรง Dev ได้มากเพราะสามารถรียูส Geth Stack หรือ Client ตัวอื่นๆ ได้ทั้งก้อน

➡️ Nitro บันทึกบาง State ("the state of ArbOS") ใน special account โดยใช้ special memory layout เพื่อแม็ป storage slots (เป็นเรื่องของ architecture ล้วนๆ user ไม่รู้สึก)
➡️ Bedrock แตกต่างเล็กน้อยโดยจะบันทึกลงใน EVM contracts ทั่วๆ ไป (จริงๆเรา implement ArbOs ด้วย EVMได้)
Bedrock เมื่อ Determine/executing block ถัดไปของ L2 จะดูที่ -Header ของ Headerของ L2 chain -อ่าน data จาก L1 -บาง dataใน EVM contract บน L2 chain บน Bedrock ถ้า Node ไหนล่มมันจะรีตัวเองทันทีโดยไม่ต้องเก็บฐานข้อมูลพิเศษเพราะอยู่ใน L1/L2 block ครบ - Nitro ก็น่าจะคล้ายกัน

Nitro ประมวลผลแมสเสจจาก L1-L2 (หรือที่เรียกว่า Deposit txn) ดีเลย์ที่ 10min
Bedrock ยืนยันโดยใช้ Block ประมาณนึง (ประมาณ2min) โดยมี parameter ชื่อ "sequencer drift" ที่สามารถทำ Timestamp L2 block ให้คล่อม L1 Block ได้ ถ้าหากเกิน 10min โดยไม่มี Deposit ก็จะถูกตีกลับ
➡️ Nitro ใน WPP อธิบายเรื่องดีเลย์ 10min เพื่อป้องกันการ Re-Org แต่ไม่มีอธิบายว่าแล้ว L2 จะรับมือกับการ Re-Org บน L1 ยังไง คนเขียนเดาว่าน่าจะไม่ทำอะไร ซึ่งก็ Work ในบางเคส
➡️ Bedrock จะรับมือกับการ Re-Org บน L1 ด้วยการ Re-Org บน L2 ถ้าจำเป็น

ถ้าคุณกำลังบริดจ์ โดย L1 ล็อกเหรียญเรียบร้อย แต่คำสั่งบน L2 เฟล คุณจะต้องสามารถเริ่มคำสั่งบน L2 ใหม่ได้ (อาจเสียแกสเพิ่ม) ไม่งั้นจะเสียเหรียญทั้งหมด
➡️ Nitro อิมพลิเมนต์เป็น "retryable tickets" สำหรับการส่ง Msg จาก L1-L2 โดยใช้ ArbOS
➡️ Bedrock ทำทั้งหมดนี้โดยใช้แค่ Solidity

L2 Fee ทั้งคู่ใช้ระบบเดียวกันโดยคิดจาก Exec Gas บน L2 + cost จาก L1 Calldata
➡️ Nitro ใช้ระบบใหม่โดยเฉพาะ ซึ่งคิดและออกแบบมาอย่างดี (Elegant) เพื่อให้ลงตัวกับ 1block/1txn
➡️ Bedrock รียูสจาก EIP-1559 ซึ่งทำงานได้ดีกับ Block Time 2 วิ และดีสำหรับการคำนวณของ Wallet/Tools

L1 Fee คิดต่างกัน
➡️ Bedrock คำนวณ L1 Fee โดยดูย้อนหลังที่ L1 basefee data ทำให้ได้ราคาค่อนข้างเรียลไทม์ (หลักการเดียวกับ Deposit) แต่เพราะ L1 Fee มีโอกาสพุ่งตลอดเวลาเลยต้องชาร์จ Multiplier เล็กน้อยของราคาที่คาด ค่า Multiplier ปัจจุบันถูกปรับลดจากตอนเริ่ม+จะลดลงอีกด้วย EIP4844
OP เลือกทางนี้เพราะจะทำให้สามารถเก็บ Fee จาก MEV ได้เพิ่ม เพื่อนำมาแจกจ่าย OP User ได้
➡️ Nitro คิดระบบที่ซับซ้อน โดยใช้ระบบควบคุมที่สามารถรับข้อมูลราคาที่ต้องจ่ายบน L1 แปลว่าถ้า Sequencer จ่ายน้อยก็คิดกับ User น้อย/จ่ายมากคิดมากขึ้น

Fault proof ต่างกัน
➡️ OP ใช้ Cannon (อิมพลิเมนต์ on Top Bedrock) และ Compile=MIPS
➡️ Nitro Compile=WASM ซึ่งเปลี่ยน output มากกว่า เรียกว่า WAVM โดยทั้งคู่แทนที่ floating point (FP) operations โดยใช้ library calls (Bedrock ใช้ GO ทำสิ่งนี้)

➡️ Bedrock fault proof รันโดยใช้ minigeth เพื่อยืนยันความถูกต้องของ state root และโพสต์บน L1 โดยใช้ Cannon ในการหา state root ที่เห็นแย้ง
➡️ Nitro โพสต์ state root เป็นก้อนๆ (RBlock) บน L1 เริ่มจากหา State root ที่ challenger/def เห็นไม่ตรงกันก่อนแล้วหา WAVM ที่เห็นไม่ตรงกันต่อ

Preimage Oracle validator software ถูกใช้สำหรับ Fault Proof ในการอ่าน L1/L2 data สุดท้ายแล้วมันจะรันที่ L1 (เข้าถึง L2 ก็ต้องเข้าผ่านL1) เราจะอ่านข้อมูล state/chain ยังไง? Merkle Root Node คือ hash ของลูกๆ เมื่อคุณรีเควส Preimage เพื่อดู state tree ก็จะเห็นทั้งหมด(พ่อ/ลูก)
เช่นเดียวกัน คุณสามารถหา Preimage ของทั้งเชนย้อนหลังโดยรีเควส preimage ของ block header (ในทุก Block Header จะมี Hash ย้อนไปถึง parent) เมื่อ Execute on-chain จะออกมาเป็น WAVM หรือ MIPS นี่คือวิธีการอ่านข้อมูล L2 ของทั้ง Nitro และ Bedrock
สำหรับ L1 ก็คล้ายกัน ต่างกันที่ก้อน Txn จะถูกเก็บใน L1 Calldata เข้าถึงผ่าน Smart Contract L1 ไม่ได้
➡️ Nitro เก็บ hashes ของทั้งก้อนใน L1 contract นี่คือเหตุผลที่ "Sequencer Inbox" เป็น Contract ต่างกับ Bedrock ที่เป็น EOA
➡️ Bedrock ไม่ต้องเก็บ Hash ใดๆ (ทำให้ประหยัดค่าแกสได้มากกว่า) แต่พวกเขาจะใช้ข้อมูลจาก Callata โดยเริ่มจากย้อนกลับไปใช้ L1 block headers และหา transaction Merkle root จะเจอก้อนข้อมูลใน calldata

➡️ Bedrock เจอสิ่ง "large preimage problem" เพราะต้อง Invert ให้ receipts preimage บางตัว ซึ่งในนั้นมี log data เรียงต่อกันยาวๆ ทำให้เสี่ยงถูกโจมตี ด้วยการอัด Log มหาศาลเพื่อสร้าง large preimage สิ่งนี้จะถูกแก้ด้วย zk-proof ในอนาคต (OPไม่เก็บ hash เพื่อลด cost การเก็บ+compute)
➡️ Nitro ใน WPP มีพูดเรื่องการแก้ L2 Preimage ขนาดใหญ่ที่ 110kb แต่ไม่มีพูดถึง L1

➡️ Nitroโยงก้อน Txn เข้ากับ State root อย่างแน่นหนา และโพสต์ชุดของข้อมูลใน RBlock ซึ่งมี State Root ด้วย
➡️ Bedrock โพสต์แต่ละก้อนแยกจากกันเพื่อลดค่าใช้จ่าย (ไม่ต้อง Interact กับ Contract หรือเก็บข้อมูลใดๆ) และโพสต์ก้อน Txn บ่อยขึ้นแต่โพสต์ State root น้อยลง
ชาเลนจ์ของ Nitro คือ RBlock ถูกชาเลนจ์ได้มั้ย? และ Txn ในนั้นจะไม่ Replayed บนเชนใหม่
ส่วนของ Bedrock ทางทีมยังคุยกันอยู่ว่าถ้า state root ถูกชาเลนจ์จะทำยังไง จะ Replay Txn เก่าบน State Root ใหม่มั้ย หรือจะ Rollback หมดเลย
จะเห็นว่าในความเหมือนของทั้งสองสิ่งนี้ มีดีเทลที่แตกต่างกันพอสมควร บางเรื่อง User อย่างเรารู้สึกได้ บางเรื่องก็ลึกระดับ Dev เท่านั้นที่เข้าใจ ขอบคุณที่อ่านมาถึงตรงนี้ สำหรับพาร์ทที่ Technical มากๆ จนต้องใช้ทับศัพย์และอาจแปลผิดหรือคลาดเคลื่อนไปบ้าง รบกวนแนะนำเพื่อปรับแก้ครับ
Share Dialog
Share Dialog
thesleeper (✨🔴_🔴✨)
thesleeper (✨🔴_🔴✨)
No comments yet