Facebook Libra focus on validator’s config & key pairs

Apisak Srihamat
3 min readAug 14, 2019

--

วันนี้ขอพักเรื่อง consensus ก่อนนะครับ เนื่องจากเมื่อวานในขณะที่กำลังรัน docker เพื่อศึกษาเรื่อง consensus อยู่นั้น ผมพบ error DeserilizationError ในขณะโหลด config network_identity_private_key ใน source code libra ล่าสุด ผมก็ได้ fix error และสร้าง PR#549 เพื่อแจ้งให้ทีมงานพัฒนา Libra ทราบ ซึ่งพี่ Konstantinos Chalkias และพี่ Michael Gorven ก็ใจดีแนะนำข้อมูลที่น่าสนใจเกี่ยวกับ config & key pairs วันนี้ผมจึงจะเข้าไปศึกษาเรื่องนี้สักหน่อยครับ

เริ่มแรกเลยเราได้ข้อมูลมาว่า configs & key pairs ของ validators ถูกสร้างขึ้นจาก terraform/validator-sets/build.sh ก็เปิด code มาดูสิค้าบบบ

จะเห็นว่ามีการเรียกใช้ rust package generate_keypair เพื่อสร้าง mint.key และ libra-config เพื่อสร้าง config key สำหรับแต่ละ validator ตามจำนวนที่ระบุเมื่อเรียกใช้ build.sh
main function ของ rust package generate_keypair
function create_faucet_key_file ของ rust package generate_keypair
API generate_keypair ของ module compat ที่ถูกสร้างขึ้นเป็น PureEdDSA โดยอ้างอิง ed25519
แล้วในที่สุดเราก็พบกับจุดที่สร้าง private key (mint.key) มันคือ function generate_for_testing ที่ไปเรียกใช้ function generate ของ library ed_25519_dalek โดยได้รับ cryptographically secure pseudorandom number generator (CSPRNG) เข้าไปนั่นเองครับ

ทุกวันนี้มันง่ายมากในการจะ สร้าง key หรือแม้แต่ encrypt/decrypt แต่หากเราย้อนกลับไปในอดีตนั้น มันต้องใช้นักคณิตศาสตร์มากมายเพื่อจะทำมันขึ้นมา ลองหาหนังเรื่อง The Imitation Game มาดูแล้วจะเข้าใจนะครับ

เมื่อเข้าใจการสร้าง mint.key แล้ว เราลองมาดูขั้นตอนการสร้าง config key กันดูบ้างนะครับ

main function ของ rust package libra-config

เนื่องจาก main function ของ rust package libra-config ค่อนข้างยาวนะครับ สามารถสรุปการทำงานได้ดังนี้

เริ่มทำงานโดยการตรวจสอบความถูกต้องของ arguments ดังนี้

  • b คือ base config ที่จะใช้
  • n คือ จำนวน nodes ที่จะทำการ config
  • o คือ output directory
  • d คือ การสร้าง peer config เพียงแค่ peer เดียวเท่านั้น (เพื่อการ force discovery)
  • s คือ การระบุ seed เพื่อสร้าง keys สำหรับแต่ละ validator
  • m คือ file location ที่จะ load faucet account ที่สร้างมาจาก generate_keypair (mint.key นั่นเองครับ)

ภายหลังจากตรวจสอบความถูกต้องของ arguments แล้วก็จะสร้าง object SwarmConfigBuilder แล้วทำการ load ค่า argument ที่มีเข้าไป แล้วจึงทำการสร้าง file config ออกมาด้วย function build ซึ่งจะไปเรียกใช้ constructor ของ object SwarmConfig เพื่อสร้าง file config ครับ

การเรียกใช้ function build ของ object SwarmConfigBuilder จาก main ของ rust package libra-config
constructor ของ object SwarmConfig

constructor ของ object SwarmConfig ค่อนข้างยาวนะครับ สามารถสรุปการทำงานได้ดังนี้ครับ

  1. สร้างไฟล์ trusted_peers.config.toml
  2. สร้างไฟล์ genesis.blob (binary genesis transaction)
  3. สร้างไฟล์ seed_peers.config.toml
  4. Random config services’s port ในไฟล์ node.config.toml
  5. สร้างไฟล์ peer_keypairs ([node id].node.keys.toml)

เอาละครับเมื่อเราพอเข้าใจ source code ของการ build crypto config key แล้ว เรามาทดสอบ build crypto config key สำหรับ validator 4 nodes กันดีกว่า ซึ่งผมจะ build 2 ครั้งใน folder ที่แตกต่างกัน เพื่อเตรียมทดสอบความแตกต่างกันครับ

ทดลอง build key สำหรับ 4 node ไปไว้ใน folder ชื่อ apisak :)
ทดลอง build key สำหรับ 4 node ไปไว้ใน folder ชื่อ srihamat :)
ผลการทดสอบคือไฟล์ [node id].node.keys, genesis.blob, mint.key นั้นเหมือนกันเลยครับ (รวมถึง consensus private/public key) แต่แตกต่างที่ node.config, seed_peers.config, trusted_peers.config (อย่าลืมว่ายังคงมี option arguments อื่นๆให้ทดสอบนะครับ)
ตัวอย่างข้อมูลด้านในของไฟล์ [node id].node.keys นะครับ จะเห็นว่ามีข้อมูล network_signing_private/public_key, network_identify_private/public_key, และ consensus_private/public_key
compare node.config.toml อ้าวววว ! Port ของ node ในวงการสนทนา validator network ดันแตกต่างไปแล้ว
compare seed_peers.config.toml ก็เป็นการสุ่มเลือก node id และ port ที่แตกต่างออกไป
ส่วน trusted_peers.config.toml นั้นเหมือนเดิมครับ เพียงแค่เปลี่ยนตำแหน่ง

Note: ns = network_signing_public_key, ni = network_identify_public_key และ c = consensus_public_key

จากความเข้าใจของผมในการออกแบบวิธีการปรับ config แบบนี้คือ port ต่างๆภายใน validator network (แน่นอนว่ารวมถึง key ต่างๆด้วย) สามารถเปลี่ยนแปลงได้ตลอดเวลาเพื่อความปลอดภัย รวมถึง admission control service port ซึ่งตอนแรกเราเข้าใจว่าจะรับการ connect จาก client แต่หากออกแบบไว้แบบนี้ คงจะมี proxy มากั้นระหว่าง client นะครับ เพราะ assume ว่า client จะไม่มีทางรู้การเปลี่ยนแปลง config แน่นอน และ client ควรจะจำแค่ว่า connect เข้ามาที่ admission control ด้วย port ใด port หนึ่ง เช่น port 8000 เสมอ นอกจากนี้ระบบเครือข่าย network หลังบ้านคงจะปวดหัวไม่น้อยกับการ ปรับ config port หากมีการเปลี่ยนแปลงบ่อยๆ ก็คงจะต้องมีการออกแบบ “method” และ “network architecture” ที่จะทำให้ network configuration ดังกล่าวสามารถนำไปใช้ได้อัตโนมัติต่อไป เช่นการ load node.config.toml ไปบังคับใช้ใน network architecture ได้อย่างอัตโนมัติ (ทุกๆ node) และมันควรจะเปลี่ยนพร้อมๆกันด้วยความรวดเร็วโดยไม่มีผลกระทบกับผู้ใช้งานครับ ตอนนี้ผมเข้าใจว่าคงหนีไม่พ้นการ translate node.config.toml ไปเป็น AWS’s network configuration เพราะได้ข่าวว่าพี่ๆเขามีการทดสอบบน AWS กันอยู่ด้วย ^ ^

นี่แค่ building validator’s config & key pairs นะครับยังไม่รวมการเอา key pairs ไปใช้งาน สงสัยคงต้องมีตอนต่อไปเพราะวันนี้เวลาหมด หมดเวลาอีกเช่นเคยครับ

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

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.