Facebook Libra focus on Consensus (Part 1)
วันนี้มาเรียนรู้เรื่อง consensus กันนะครับ จากความเดิมตอนที่แล้วเรื่อง Facebook Libra focus on Mempool ภายหลังจากใน mempool มีข้อมูล transaction ที่จัดเรียง priority เอาไว้รอที่จะให้นำไปกระทำการยืนยันต่อครับ หากสนใจทำความเข้าใจกันเล็กน้อยเกี่ยวกับทฤษฎีให้อ้างอิง Life of a transaction, State Machine Replication in the Libra Blockchain, FBFT และ Hotstuff นะครับ เราสายลุยไม่คุยให้เสียเวลามาเปิด code libra ดูกันเลยครับ
จาก code libra นั้น consensus’s README อธิบายไว้ว่า consensus components ถูกพัฒนาเป็น Actor model มี message คุยกันระหว่าง sub-components ด้วย tokio framwork ซึ่ง actor model (ที่ถูกเข้าถึงโดยหลายๆ sub-components ณ เวลาใดๆ) คือ consensus data structure “BlockStore” ซึ่งคอยจัดการ blocks, execution, quorum certificates และ shared data structure อื่นๆ
Consensus มี components หลักๆดังนี้
- Transaction Manager เป็น interface ไปที่ mempool และทำการ pulling transactions และ removing transactions ที่ committed ไปแล้ว ซึ่ง proposer ใช้การ pull transactions ที่ต้องการจาก mempool เพื่อจะสร้าง proposal block.
- State Computer เป็น interface สำหรับการ execution สามารถ execute blocks, commit blocks และ sync
- BlockStore มีหน้าที่เก็บ tree ของ proposal blocks, block execution, votes, quorum certificates, และ persistent storage. นอกจากนี้ยังเก็บรวบรวมโครงสร้างข้อมูลให้ถูกต้องและเข้าถึงได้จากส่วนงานอื่นๆ
- EventProcessor มีหน้าที่ประมวลผลแต่ละ events (เช่น process_new_round, process_proposal, process_vote) โดยจะทำการประมาลผลแบบ async สำหรับแต่ละ event type และ drive protocol.
- Pacemaker มีหน้าที่ทำ liveness consensus protocol โดยจะเปลี่ยนรอบการทำงานทุกๆ timeout certificates หรือ quorum certificates และ proposes blocks เมื่อมี proposer สำหรับรอบนั้นๆ
- SafetyRules มีหน้าที่ดูแลความปลอดภัยของ consensus protocol. ซึ่งจะประมวลผล quorum certificates และ ledgerinfo เพื่อที่จะเรียนรู้เกี่ยวกับ new commits และ guarantees ว่ามีมากกว่า 2 voting rules แล้ว รวมถึงกรณีที่เกิดการ restart (ตั้งแต่ safety data ยังอยู่ใน local storage)
เอาล่ะ มาตอบคำถามง่ายๆกันว่า TransactionManager มันเริ่มรันได้ยังไง เนื่องจากเป็นการเริ่มทำงานที่แตกต่างจากส่วนอื่นๆที่เราเคยศึกษาที่มี client เป็นผู้เริ่มเรียกใช้งาน โดยการ revert engineering ไล่ย้อนจาก TransactionManager มีอยู่ 2 functions :)
- function pull_txns: จะถูกเรียกโดย object ProposalGenerator ใน function generate_proposal
- function commit_txns: จะถูกเรียกโดย object EventProcessor ใน function process_commit
เริ่มที่ pull_txns ก่อนนะครับ function generate_proposal ซึ่งถูกเรียกต่อมาจาก process_new_round_event อีกทีนึง โดยมันจะถูก trigger เพียงครั้งเดียวในแต่ละรอบ (round) โดย new quorum certificate หรือ timeout certificate จากรอบก่อนหน้า ซึ่งลักษณะการทำงานเป็น task (TaskExecutor ของเจ้า tokio) จะ spawn process_new_round_events ที่มี while loop วนทำงานวนเป็นรอบอยู่ตลอดเวลา ซึ่งจริงๆแล้ว function start ของ StateMachineReplication จะไล่ start_event_processing (spawn) processes ดังนี้
- process_new_round_events (เรากำลังสนใจ process นี้แต่เดี๋ยวคงจะเชื่อมกันหมด ^^”)
- process_proposals
- process_wining_proposals
- process_block_retrievals
- process_chunk_retrievals
- process_vote
- process_timeout_msg
- process_outgoing_pacemaker_timeouts
- process_sync_info_msgs
อย่างไรก็ตามใน async function process_new_round_event ผมเห็นว่า libra developer มี debug! Propose มาดูจึงไม่รอช้าทดสอบเปิดดู log ตาม จำได้จากบทความก่อนหน้านี้ว่า consensus มันมีความพยายามที่จะส่ง event(s) กันตลอดเวลาแม้เราจะไม่ได้ส่ง command account mint หรือ transaction ใดๆ ผมตัดรูปมาในส่วนที่มันจะมีการ repeat sequence การทำงานประมาณนี้อยู่ตลอดเวลา (Highlight สีเหลืองคือแต่ละ process ที่ spawn ออกมาที่มีการ debug)
ใครเป็นคนส่ง certificate event มาให้ในแต่ละ round ? ในขั้นตอนนี้ผมใช้วิธีค้นหาจากผู้ใช้งาน sender และ NewRoundEvent จึงพบว่า function create_new_round_task ของ object LocalPacemakerInner เป็นผู้สร้าง NewRoundEvent มาโดย NewRoundReason จะถูก pass parameter เข้ามาจาก caller
แล้วใครเรียกใช้งาน create_new_round_task บ้างล่ะ ?
- function update_current_round ของ object LocalPacemakerInner (QCReady หรือ timeout) => ถูกเรียกมาจาก function process_certificates, process_remote_timeout ของ object Pacemaker
- Constructure ของ LocalPacemaker (QCReady) => ถูกเรียกจาก function create_pacemaker ของ object ChainedBftSMR ซึ่งจะถูกเรียก (ครั้งเดียวตอนเริ่มทำงาน) ใน function start ของ object StateMachineReplication
มาถึงตรงนี้จะเห็นว่า Pacemaker นั้นเองที่เป็นผู้สร้าง event ในแต่ละรอบ จะว่าไปเราได้อธิบายแล้วว่า Pacemaker เป็น component ที่มีหน้าที่ “liveness” consensus protocol ในตอนต้นนะครับ :)
“Pacemaker มีหน้าที่ทำ liveness consensus protocol โดยจะเปลี่ยนรอบการทำงานทุกๆ timeout certificates หรือ quorum certificates และ proposes blocks เมื่อมี proposer สำหรับรอบนั้นๆ”
โดยสรุปแล้ว ตอนนี้เราเริ่มเข้าใจวิธีการทำงานของ “background process” หรือในอีกชื่อนึงคือ “EventProcessor” และบางส่วนของ component “Pacemaker” แล้วว่ามีการทำงานร่วมกันอย่างไร มีอีกหลายเรื่องที่น่าสนใจ เช่น รายละเอียดการทำงานของ TransactionManager, การ proposes blocks เมื่อมี proposer, State computer และ Safty Rules เป็นต้น ยังไงคงต้องติดเอาไว้ก่อนนะครับ หวังว่าจะมีโอกาสและเวลาได้ศึกษา libra’s consensus ต่อไป
บทความอื่นๆเกี่ยวกับการทำความเข้าใจ source code libra มีดังนี้ครับ
Facebook Libra on Windows is easy
Facebook Libra focus on account create
Facebook Libra focus on account mint
Facebook Libra focus on query balance
Facebook Libra focus on admission control (Part 1)