Facebook Libra focus on Admission Control (Part 1)

Apisak Srihamat
3 min readJul 23, 2019

--

วันนี้เรามาเรียนรู้เรื่อง Admission Control กันนะครับ แต่ก่อนจะไปถึงตรงนั้นเรามาสรุปความเข้าใจของ libra command กับสิ่งที่เราได้เรียนรู้ไปประมาณอาทิตย์ที่ผ่านมาโดยผมทำเป็นรูปสรุปไว้ด้านล่างนี้แล้วครับ

Command account create code hierarchy และ โครงสร้างที่เรารู้
Command account mint และขั้นตอนที่เรารู้
Command query balance และโครงสร้างที่เรารู้
Command transfer และโครงสร้างที่เรารู้

โดยจากข้อมูลที่เรารู้จะเห็นว่าการทำงานของ admission control มี 2 function หลักและมีการเรียกใช้ดังนี้

  1. UpdateToLatestLedger: ใช้โดย account create และ query balance
  2. SubmissionTransaction: โช้โดย account mint (sender is zero) และ transfer

ครั้งนี้ผมจะใช้ libra_swarm แทนที่จะเชื่อมต่อ testnet และผมจะใช้งาน debug! แทนที่จะใช้งาน println! เหมือนทุกๆครั้งที่ผ่านมานะครับ โดยเราจะใช้ RUST_LOG=debug เพื่อรัน libra_swarm ดังนี้ครับ

$ RUST_LOG=debug cargo run -p libra_swarm -- -s

เมื่อรันคำสั่งจะมีข้อความบอกว่า log directory อยู่ที่ /tmp/.tmpmlHc7X
เปิดอีกหน้าต่างนึงเพื่อเข้ามาดูใน folder จะเห็นว่าเก็บข้อมูล logs, configs และ libradb … แหม่มมมมม…. น่าเข้าไปดู libradb จริงๆเลยมีอะไรบ้างนะแต่ใจเย็นๆนะครับเรายังคง focus ที่ admission control ก่อน เพราะฉะนั้นเข้าไปที่ folder logs ก่อนนะครับ :)
พิมพ์คำสั่ง tail -f [ชื่อไฟล์.log]
จะเห็นว่ามีการกระทำงาน consensus และงานที่เกี่ยวข้องกับ storage อยู่ตลอดเวลาเลยซึ่งค่อนข้าง over information ในกรณีที่เราต้องการเรียนรู้การทำงานของ admission control
ให้เปลี่ยนไปใช้คำสั่ง tail -f [ชื่อไฟล์.log] | grep admission แทนนะครับ เมื่อผมทดสอบคำสั่ง account create ในอีกหน้าจอ libra ในเวลาเดียวกันจะเห็นว่ามีงานที่เกี่ยวข้องกับ admission control เข้ามาและมี time stamp ให้เปรียบเทียบระหว่าง process ได้ด้วย สะดวกดีนะครับ :)
ใช้คำสั่ง account create ที่หน้าจอ libra ในเวลาเดียวกัน
ซึ่ง debug message นี้คือข้อความที่ทีมงาน libra เอาไว้ debug ดูข้อมูลระหว่างพัฒนา ว้าวววววว เรากำลังมองสิ่งเดียวกับพวกเขา:)

เอาล่ะครับ เมื่อเครื่องมือพร้อมแล้วเรามาเริ่มทำความเข้าใจกันที่ UpdateToLatestLedger ละกันนะครับ ดูแล้วน่าจะง่ายกว่า ส่วน SubmitTransaction เอาไว้แบ่งเป็นบทความถัดไป (ถ้ามี) ก็แล้วกันครับ :)

function update_to_latest_ledger_inner ของ admission control service ที่ถูกเรียกมาจาก API update_to_latest_ledger ของ admission control service

จะเห็นว่ามีการเรียก storage_read_client แล้วส่ง client_known_version และ account’s address แล้วจะได้รับค่า 3 ค่ากลับมาคือ response_items, ledger_info_with_sigs, validator_change_events จากนั้นจึงนำมาปรับ format พร้อมส่งกลับไปเป็น response

การประกาศ storage_read_client เป็น gRPC ไว้ครับ
function update_to_latest_ledger ของ StorageReadServiceClient ก็ไปเรียก update_to_latest_ledger_async แบบ block แสดงว่าเป็น syncronize สินะ ^^”
update_to_latest_ledger_async ของ StorageReadServiceClient สำหรับคนที่ไม่ค่อยถนัด Rust อ้างอิง Pin, Box, Dyn, Send
Comment ที่ บอกว่ามีการ mapping 1–1 ระหว่าง LibraDB API และ storage read client interface ซึ่งเราพบว่า update_to_latest_ledger_async จะ map กับ libraDB Public API update_to_latest_ledger
Public API update_to_latest_ledger ของ LibraDB ผมจัดการใส่ debug code เพื่อให้มั่นใจว่ามันถูกเรียกจริงๆ
ผลลัพธ์ที่ได้พบว่ามีการ print debug ข้อมูล ledger_info_with_sigs และ ledger_version เมื่อเรียกใช้ account create จากอีกหน้าต่างนึง

Public API update_to_latest_ledger ของ LibraDB ค่อนข้างยาวนะครับแต่ในความเป็นจริงแล้วจะสามารถเลือกดึงข้อมูลเฉพาะที่อยู่ใน RequestItems เท่านั้น เป็นการออกแบบ Public API ที่เอาไว้ใช้ในหลายสถานะการณ์โดยสามารถเลือกข้อมูลได้ดังนี้

  1. GetAccountState
  2. GetAccountTransactionBySequenceNumber
  3. GetEventsByEventAccessPath
  4. GetTransactions
ย้อนกลับไปดูกรณี account create และ query balance ต้องการข้อมูล GetAccountState ครับ :)

มาถึงตรงนี้การติดตามลึกลงไปในส่วนการเชื่อมต่อ LibraDB ก็น่าสนใจเช่นเดียวกัน แต่เนื่องจากอาจจะทำให้บทความยาวมากๆ ผมอาจจะขอแยกบทความออกไปสำหรับเรื่องนั้น (ถ้ามี) นะครับ

ที่หัวของไฟล์ที่ implement storage ได้บอกไว้ชัดเจนว่าทีมงาน libra มีแผนที่จะเปลี่ยนแปลงวิธีการเก็บข้อมูลในอนาคตครับ เขาจึงได้แยก module storage เป็น gRPC เอาไว้ในลักษณะ micro service เพื่อจะได้ปรับเปลี่ยนได้ง่ายในอนาคต

อย่างไรก็ตามเมื่อได้รับ response จาก storage read service แล้วทาง admission control ก็ส่งกลับไปที่ทาง client ซึ่งทาง client ก็จะตรวจสอบอีกครั้งหนึ่งตามที่ได้อธิบายไปแล้วตอนทำความเข้าใจเรื่อง query balance แต่ไหนๆก็ไหนๆแล้ว เรามา debug response ที่ admission control ได้รับมาสักหน่อยดีกว่าครับ โดยย้อนกลับไปที่ function update_to_latest_ledger_inner เพื่อเพิ่ม debug code

function update_to_latest_ledger_inner ของ admission control (with debug code)
หน้าต่างแรกใช้งาน libra_swarm สำหรับส่งคำสั่ง account create
Result ของ debug code ที่เราเพิ่มเข้าไป (โดยดูจากวิธี grep)

Note: ที่หน้าต่าง tail log จะเห็นว่า ข้อมูลหายไปเล็กน้อย เราไม่เห็น validator_change_events ซึ่งเป็นค่าว่างในฝั่ง client และข้อมูลบางส่วนของ ledger_info_with_sigs คาดว่าน่าจะเป็น limit ของการใช้คำสั่ง grep ครับ อย่างไรก็ตามหวังว่าบทความนี้จะมีประโยชน์ ไม่มากก็น้อย ราตรีสวัสดิ์ครับ :)

บทความอื่นๆเกี่ยวกับการทำความเข้าใจ 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 2)

Facebook Libra focus on mempool

Facebook Libra focus on consensus (Part 1)

Facebook Libra focus on create testnet-like

Facebook Libra focus on consensus (Part 2)

--

--

Apisak Srihamat

Master of Science AIT, Embedded systems course UC Irvine, Bachelor of Computer Engineering KMITL, Love innovation ideas.