ทุกวงการจะมี Tipping Point (จุดเปลี่ยนผันอย่างชัดเจน) อย่างของมือถือก็เป็น iPhone แต่สำหรับวงการ Cryptocurrency นั้นยังไม่มี Tipping Point ที่ชัดเจนเท่าไหร่นัก ที่ผ่านมาเหมือนเป็นกระแส FOMO (Fear of missing out) ซะมากกว่า แต่วันนี้เริ่มเห็นจุดเปลี่ยนครั้งใหญ่แล้วเมื่อผู้เล่นยักษ์ใหญ่อย่าง Facebook ได้ออกเหรียญของตัวเองอย่าง Libra ร่วมกับ Partner ยักษ์ใหญ่มากมายมหาศาล และพอได้อ่านรายละเอียดก็ทำให้เห็นว่าเหรียญนี้ไม่ได้ทำมาเพื่อตามกระแสแต่อย่างใด แต่ทำมาเพื่อใช้ประโยชน์จริง ๆ และคิดว่าน่าจะมีประโยชน์มากด้วย
หลังจากนั่งอ่าน Whitepaper เอกสารต่าง ๆ พร้อมกับเล่นเองมาหน่อยนึง วันนี้เลยขอมาสรุปให้ฟังกันว่าเจ้าเหรียญ Libra นี้คืออะไร มีแนวคิดยังไง และจะสร้างปรากฎการณ์อะไรหลังจากนี้ได้บ้างครับ
"สกุลเงินที่ใช้ร่วมกันทั่วโลก" คือมิชชั่นของ Libra
เพื่อเป็นเกียรติแก่ Libra ที่เขียน Whitepaper มาหนาปึก เลยขอยกมิชชั่นและเป้าหมายของ Libra มาให้ดูทั้งย่อหน้าก่อนดังนี้
The goal of the Libra Blockchain is to serve as a solid foundation for financial services, including a new global currency, which could meet the daily financial needs of billions of people. The blockchain has been built from the ground up to prioritize scalability, security, efficiency in storage and throughput, and future adaptability.
สรุปง่าย ๆ คือ Libra ถูกออกแบบมาให้เป็น "สกุลเงินที่ใช้ร่วมกันทั่วโลก (Global Currency)" นั่นเอง
จริง ๆ มันก็คือสกุลเงินเหมือนที่เราใช้ ๆ กันนี่แหละ ไม่มีอะไรต่างจากเดิมคือใช้ซื้อของ ใช้โอนไปมาหากัน ฯลฯ แต่ก่อนหน้านี้สกุลเงินเป็นของประเทศใครประเทศมันเนื่องด้วยเหตุผลหลัก ๆ ก็คือเพื่อเหตุผลทางเศรษฐกิจระดับประเทศ และเพื่อให้ง่ายต่อการควบคุมปริมาณเงิน
ก่อนหน้านี้ก็มีความพยายามจะสร้างสกุลเงินตรงกลางที่ใช้กันได้ทั่วโลกมาแล้ว ความจริงก็มีอยู่แล้วหละก็คือ US Dollar ซึ่งถือเป็น Global Currency (หรือเรียกอีกอย่างว่า Reserve Currency) ที่ใหญ่ที่สุด รองลงมาก็ Euro แต่จะเป็นการใช้ในลักษณะการสำรองเงินระดับรัฐบาลเพื่อพิมพ์สกุลเงินท้องถิ่นมากกว่า แต่ถามว่าคนในประเทศนั้น ๆ ใช้ US Dollar ซื้อของกันมั้ย ก็ไม่
ซึ่งนี่แหละ สกุลเงินที่ "ทุกคน" ใช้ด้วยกันหมดทั้งโลกแบบจริง ๆ มันก็เลยยังไม่มี สร้างมากี่อันก็ล้มเหลวหมดเพราะไม่มีความน่าเชื่อถือ ต่อให้ผู้เล่นใหญ่แค่ไหนก็น่ากังวลอยู่ดี นี่มันเรื่องของเงินเลยนะ !
แต่ด้วยระบบ Blockchain ที่มีความเชื่อถือได้สูง ทุกอย่างโปร่งใส ถูกพิสูจน์มาแล้วจากเทคโนโลยีที่เปลี่ยนจากคำพูดที่หรูหราให้เป็นการใช้งานได้จริงในช่วงสองสามปีที่ผ่านมา ทำให้ Facebook จึงตัดสินใจสร้างสกุลเงินใหม่ขึ้นมาบนเทคโนโลยี Blockchain และปล่อยออกมาเป็นสกุลที่ทุกคนจะใช้กันได้ทั่วโลกจริง ๆ โดยไม่มีคนกังขาเรื่องความน่าเชื่อถืออีกต่อไป
ดังนั้น Libra จึงถือเป็นจุด Tipping Point ใหญ่มากของวงการเงินโลก ไม่ใช่แค่วงการ Cryptocurrency นะ แต่เป็นเรื่องของการเงินระดับโลกเลยหละ
Libra เหรียญจิตวิญญาณ Stablecoin
หนึ่งในสิ่งที่เหรียญอันดับหนึ่งตลอดกาลอย่าง Bitcoin ถูกกังขามาตลอดคือ เราจะใช้มันเป็นเงินได้ไง ถ้าราคามันยังเหวี่ยงไปมาจนไม่รู้ว่ามูลค่าที่แท้จริงมันเท่าไหร่ (คุณสมบัติของสกุลเงินที่ดีคือมี Volatility หรือความผันผวนต่ำ) สุดท้าย Bitcoin จึงเป็นเหมือนทองมากกว่าสกุลเงิน ไม่เหมาะกับการใช้ซื้อของ แต่ซื้อเก็บเป็น Asset ได้
โลกจึงพยายามหาวิธีสร้างเหรียญที่มีความผันผวนต่ำจะได้ใช้งานจริงกันได้ ที่ผ่านมาจึงมีสิ่งที่เรียกว่า "Stablecoin" หรือ "เหรียญที่มีมูลค่าคงที่ไม่ว่าจะผ่านไปนานเท่าไหร่" ขึ้นมา ยกตัวอย่างเช่น เหรียญ USDT (อันฉาวโฉ่) หรือเหรียญ DAI (อันโด่งดัง) ซึ่งทั้งสองเหรียญมีมูลค่า $1 มาโดยตลอด ไม่ว่าตลาดจะผันผวนเช่นไร
ถามว่าทำได้ยังไง ? ไม่มีอะไรยากครับ มันใช้หลักการเดียวกับการพิมพ์เงินประเทศต่าง ๆ เลยหละคือ
"หาหลักทรัพย์มาค้ำประกันตามมูลค่า แล้วค่อยพิมพ์เงินออกไปตามมูลค่านั้น"
ยกตัวอย่างเช่น เอาเรือยอร์ชราคา $1,000,000 มาค้ำประกันไว้ แล้วก็พิมพ์เหรียญ YATCHCOIN ออกมาจำนวน 1,000,000 เหรียญ มูลค่าของเหรียญ 1 YATCHCOIN ก็จะเท่ากับ $1 ทันทีโดยไม่มีวันเปลี่ยนแปลง
สำหรับ Libra ก็เช่นกัน ใน Whitepaper เขียนไว้ชัดเจนว่า
It is backed by a reserve of assets designed to give it intrinsic value;
ดังนั้นเหรียญแต่ละเหรียญจึงมีมูลค่าคงที่ Libra จึงเป็น Stablecoin อย่างเต็มรูปแบบ ถ้ามีความต้องการเหรียญเพิ่ม (ก็คือมีคนใช้เหรียญเยอะจัด ๆ จนมีไม่พอให้ใช้และครอบครอง) ก็หาของมาวางค้ำประกันเพิ่มแล้วก็พิมพ์เงินเพิ่ม การทำงานเหมือนการพิมพ์เงินของประเทศต่าง ๆ เลยนั่นเองครับ
ส่วนมูลค่าต่อเหรียญจะเท่าไหร่นั้นทาง Facebook ยังไม่ตัดสินใจ ต้องรอดูกันต่อไปอีกที
มันจึงไม่ได้เกิดมาเพื่อซื้อไว้เก็งกำไรนะ
ใครคิดจะซื้อเพื่อว่าอีก 10 ปีราคามันจะขึ้นมาหมื่นเท่าก็เสียใจด้วยนะ ไม่มีวันนั้นเพราะมันจะมูลค่าเท่าเดิมตลอดปายยยย
แล้ว Libra ยึด (Peg) กับมูลค่าของอะไร ?
ก็คงเกิดข้อสงสัยว่าถ้าเป็น Stablecoin แล้ว Libra จะยึดกับมูลค่าของสกุลเงินหรือสินทรัพย์อะไร ทาง Libra ต้องการให้ความผันผวนต่ำที่สุดเท่าที่ทำได้ ก็เลยใช้ "ตระกร้าเงิน" โกยหลาย ๆ สกุลเงินเข้ามารวมไว้เพื่อให้รวม ๆ แล้วไม่เกิดความผันผวน อันนี้เป็นที่เค้าเขียนไว้ใน Whitepaper
It is important to highlight that this means one Libra will not always be able to convert into the same amount of a given local currency (i.e., Libra is not a “peg” to a single currency). Rather, as the value of the underlying assets moves, the value of one Libra in any local currency may fluctuate.
สรุปง่าย ๆ คือ Libra ไม่ได้ยึดกับสกุลเงินเดียวนะครับ เวลาแลกเปลี่ยนอาจจะไม่ใช่เรทเดิมเสมอไป แต่คงเปลี่ยนไม่มาก
แล้วจะเอาเหรียญ Libra มาครอบครองได้ยังไง ?
หลักจากองค์กรกลาง (Libra Association) เอาสินทรัพย์มาค้ำประกันและพิมพ์ (Mint) เหรียญ Libra ออกมาแล้ว องค์กรนี้ก็จะเปิดให้คนสามารถเอาเงิน Fiat (เงินที่ออกโดยรัฐบาล) มาแลกเปลี่ยนเป็นเหรียญ Libra ได้โดยตรงผ่านทางกลุ่มคนที่ได้รับมอบสิทธิ์ให้บริการรับแลกเหรียญ Libra ในภูมิภาคต่าง ๆ ซึ่งจะถูกคัดเลือกจากเครดิตระดับสเกลใหญ่เท่านั้น ร้านเล็ก ๆ คงจะเปิดไม่ได้
อันนี้คือที่เขียนใน Whitepaper
The assets in the Libra Reserve will be held by a geographically distributed network of custodians with investment-grade credit rating to provide both security and decentralization of the assets.
และความลุ้นก็อยู่ตรงนี้ ... ถ้าประเทศไหนแบนก็คงไม่สามารถมีร้านรับแลกเปลี่ยน Libra ได้ครับ
คิดว่าไทยจะแบนมั้ย ... ก็ลองเดา ๆ กันไปดูนะ
แต่ก็แหละ ตามหลักคือการซื้อขาย Libra ควรจะง่ายมาก ๆ เหมือนการแลกเงินปกติครับ
แล้วจะเปลี่ยนเงิน Libra กลับเป็นเงิน Fiat ยังไง ?
ก็เหมือนกับตอนแลกมา เราก็หาคนแลกหรือร้านรับแลกก็เป็นอันจบ
อย่างไรก็ตาม กาตัวแดง ๆ ไว้เลย ระวังข้อกฎหมายด้วยนะคร้าบบบบ รอให้ชัดก่อนเนอะ
แล้วเราจะเก็บเหรียญไว้ไหนหละ ? นี่ไง "กระเป๋า Calibra"
สำหรับเงินที่เป็นธนบัตรหรือเหรียญแบบจับต้องได้ เวลาเราได้มาเราก็เก็บใส่กระเป๋าตังค์เนอะ แต่สำหรับเหรียญ Libra ที่อยู่ในรูปแบบดิจิตอลจับต้องไม่ได้แล้วเราจะเก็บไว้ไหนหละ ?
ทาง Facebook ก็ทำแอป ฯ กระเป๋าตังค์พร้อมด้วยฟีเจอร์สำหรับทำธุรกรรมครบครันไว้เรียบร้อยนามว่า Calibra หน้าตาดีมาก
เวลาไปแลกเงินให้เป็น Libra เราก็แค่บอกชื่อกระเป๋าตังค์เราไป แล้วยอดเงินก็จะขึ้นมาให้เราเอาไปใช้ต่อได้เลยทันที หรือถ้าจะโอนเงินให้เพื่อนหรือให้คนอื่นโอนมาให้ ก็ทำผ่านแอป ฯ นี้ได้เลยเช่นกันคร้าบผม
ซึ่งการจะเริ่มใช้งาน Calibra ได้เราจะต้องทำการยืนยันตัวตน (KYC) ก่อนด้วยนะ ดังนั้นการจะใช้เหรียญ Libra ได้ก็ต้องแสดงตัวตนด้วย คงจะทำผิดกฎหมายยากหน่อย (ซึ่งดี)
ก็หวังว่าข้อมูลตรงนี้จะมี Privacy สูงพอที่รัฐจะเอาไปใช้ประโยชน์ไม่ได้นะ
สิ่งที่ขอเน้นย้ำเพิ่มตรงนี้คือ
Libra เป็นของ Libra Association เฟสบุ๊คไม่มีสิทธิ์ควบคุม ส่วน Calibra เป็นของ Facebook เต็ม ๆ คนอื่นไม่มีสิทธิ์ (แต่ก็ Operate แยกกับ Facebook นะ)
เข้าใจตรงกันน้าาา
โอนเงินเร็วมาก ค่าโอนเก็บกับคนส่งแต่ถูกมาก
จากการทดลองพบว่า ใช้เวลาโอนเร็วมากกกกก แค่ 2 วินาทีเท่านั้นก็โอนเสร็จแล้ว ปลายทางได้รับอย่างว่องไว (อย่างไรก็ตาม ตามสเปคแล้วจะต้องรอ 10 วิเพื่อให้ทุกอย่างยืนยันสำเร็จ)
ส่วนค่าส่ง (Gas) ไม่ได้ฟรีแต่ก็ถูกมากจนเรียกว่าเกือบฟรี ถึงจะยังไม่ชัดเจนว่าเท่าไหร่ แต่ก็น่าจะไม่ถึง 1 บาทครับ ต่อให้โอนเป็นล้านบาทก็เสียค่าส่งแค่นั้น
เมื่อประกอบกับข้อมูลด้านบนแล้ว หากใครต้องการโอนเงินข้ามประเทศ Libra นี่ตอบโจทย์ฝุด ๆ ค่าส่งถูก แปลงเงินง่าย (ถ้าไม่โดนแบนซะก่อน) เปรมกันไปเลยทีเดียว
แต่สำหรับการใช้จ่ายในชีวิตประจำวันอันนี้ต้องรอดูว่าตกลงค่าส่งจะเท่าไหร่กันแน่ เพราะสิ่งที่สำคัญมาก ๆ คือ ต้องคุ้มกับการโอน Micro Transaction (โอนเงินปริมาณน้อยมาก ๆ) ไม่งั้นก็เกิดยากอยู่ ซื้อข้าวมันไก่ 40 บาท ค่าโอน 1 บาท นี่ก็แพงเกินไปอยู่ดีเนอะ
รับ Transaction ได้ 1,000 Tx/s
เมื่อคาดหวังว่าจะมีคนใช้งานเยอะ เรื่องใหญ่มากของ Blockchain ที่เป็น Concern ตลอดมาคือ
"แล้วแกรสามารถรับ Transaction ได้มากสุดกี่ Tx ต่อวินาที !?"
สำหรับ Libra วันเริ่มแรกจะรับได้ที่แถว ๆ 1,000 transactions ต่อวินาทีซึ่งถือว่าน้อยถ้าคิดจะทำสเกลใหญ่แล้ว อย่าง VISA นี่รับได้ 24,000 tx/s เลย แต่ใช้จริงก็แถว ๆ 1,700 tx/s
ดังนั้นของ Libra ถึงจะน้อยแต่ก็น่าจะเพียงพอเพราะคงเริ่มต้นมาเล็กกว่า VISA มาก แล้วอนาคตน่าจะค่อย ๆ รับได้เยอะขึ้นเรื่อย ๆ ครับ
เบื้องหลังความเร็ว ... Consensus นามว่า LibraBFT
การทำงานของ Blockchain จำต้องมีเครื่องคอมพิวเตอร์ (node) จำนวนมากทำงานร่วมกัน ช่วยกันยืนยันการทำงานของระบบว่ายังถูกต้อง หากมีใครสักคนพยายามโกง node ทุกตัวก็ต้องสามารถดูออกและเลือกไม่เชื่อถือ ปฏิเสธความผิดปกตินั้นไป
หนึ่งในสิ่งสำคัญของ Blockchain ในระดับแกนกลางก็เลยคือ "ข้อตกลงร่วมกันว่าแต่ละเครื่องจะทำงานร่วมกันอย่างไร" เพื่อให้ทุกอย่างเป็นไปอย่างราบรื่นปราศจากการโกง หรือที่เราเรียกว่า Consensus นั่นเอง
สำหรับ Libra ทาง Libra Association เลือกสร้าง Consensus ใหม่ขึ้นมาเองนามว่า LibraBFT แต่ถามว่าใหม่จากศูนย์เลยหรือเปล่าก็ตอบว่าไม่ใช่ เพราะจริง ๆ มันคือ BFT-Based Protocol ที่ชื่อว่า HotStuff (ใครทำงานสายบล็อกเชนคงรู้จักกันอยู่ละ) แล้วทาง Libra ก็เอามาพัฒนาต่อเพื่อให้เหมาะสมกับการใช้งาน
ไม่ลงดีเทลมากแต่บอกว่าสาเหตุที่ Libra เลือกใช้ HotStuff มาเป็นฐานก็เพราะว่า
HotStuff นั้นเป็นโปรโตคอลที่ทำงานได้เร็วมากและสามารถสเกลได้
หากเทียบกับ BFT-Based Protocol ตัวอื่น ๆ แล้ว ตัว HotStuff สามารถเพิ่มจำนวน Node ได้เรื่อย ๆ โดยไม่มีปัญหาด้านประสิทธิภาพ
ซึ่งก็ตรงกับความต้องการของ Libra ที่อยากจะเริ่มต้นด้วย 100 nodes แล้วค่อย ๆ ขยายจนไปถึง 500 - 1,000 nodes ในที่สุดนั่นเองครับ
ความจริง LibraBFT เป็นโปรโตคอลที่ง่ายมาก ง่ายกว่า BFT ตัวอื่น ๆ เสียอีก แต่ประสิทธิภาพนี่เต็มเปี่ยมมาก ใครอยากรู้รายละเอียดเพิ่มเติมแนะนำให้อ่านตามนี้ครับ
1) Hot-Stuff โดย vmware
2) LibraBFT Consensus จากเว็บ Libra เอง
สรุปคือ Facebook วางแผนไว้แล้วว่าจะให้ Libra สเกลได้เรื่อย ๆ และจะรับ Partner เพิ่มขึ้นเรื่อย ๆ เพื่อให้รับจำนวน Transaction ได้เพิ่มขึ้นเรื่อย ๆ รวมถึงเพิ่ม Market Cap จนทะลุความต้องการของคนทั่วโลกนั่นเอง
วางแผนไว้ดีตั้งแต่ต้นแบบนี้นี่ต้องยอมรับในวิชั่น น่าจับตายาว ๆ เลย
ขั้นตอนการ Validate Transaction
หัวข้อนี้ก็จะ Geek หน่อย ๆ นะ ใครไม่ใช่นักพัฒนาจะข้ามไปเลยก็ได้ โดยส่วนนี้จะพูดถึงว่าตั้งแต่ Transaction ถูกสร้างจนถูกบรรจุลงใน Permanent Storage นี่ต้องผ่านอะไรบ้าง เริ่มต้นจาก Diagram !
ขั้นตอนมีดังต่อไปนี้
1) Client สร้าง Transaction แล้วส่งเข้า Libra Network ผ่านตัว Validator Node สักตัวในระบบ โดยตัวที่มีหน้าที่รับ Transaction เราจะเรียกว่า Admission Control หรือ AC ซึ่งเป็น Component นึงของ Node
2) AC จะส่ง Transaction นั้นเข้าเช็คเบื้องต้นที่ Virtual Machine ก่อนว่า Transaction นี้ Valid มั้ย คนส่งมีเงินพอมั้ย ถูก Replay มั้ย เป็นต้น
3) ถ้าผ่านขั้นตอน 2 ตัว AC ก็จะส่ง Transaction ไปให้ Mempool ของ Node มันเอง
4) Transaction จะถูกบรรจุไว้ใน Mempool ซึ่ง Mempool ก็คือการเก็บ Transaction ไว้ใน Memory เพื่อรอการยืนยันนั่นเอง (จนถึงตอนนี้ก็ยังเกิดอยู่ภายใน Node เดียวเท่านั้น)
5) Mempool ของ Node นี้จะส่ง Transaction ไปให้ Node ตัวอื่น ๆ เพื่อเก็บใน Mempool ของทุก Node ในระบบ
6) ระบบของ Libra จะทำการสุ่ม Validator Node (V1) ขึ้นมา 1 ตัวเพื่อดึง Transaction ใน Mempool แล้วสร้างเป็น Block แล้วส่งหา Validator Node ตัวอื่น ๆ ผ่าน Consensus Protocol
7) Consensus Component ของ V1 จะทำการคุยกับ Validator Node ตัวอื่น ๆ ว่ายอมรับ Block ที่ส่งไปมั้ย
8) ระหว่างที่รอคุยกับ Validator ตัวอื่น ๆ V1 ก็ไม่รอช้า ส่ง Block ไปให้ Execution component เพื่อเตรียมรอเอาไปรัน
9) Execution component ส่ง Block ไปรันใน Virtual Machine รอไปพลาง ๆ เพื่อเอาผลลัพธ์เตรียมเก็บไปบรรจุลง Storage ถ้าทุกคนตอบกลับมาว่ายอมรับ (Asynchronous มาก ๆ)
10) หลังจากรันโค้ดในขั้นตอนที่ 9 เสร็จ ตัว Execution ก็จะเอา Transactions ใน Block ไปต่อท้ายใน Merkle Accumulator ในเมมมอรี่ (เป็นโครงสร้างการเก็บข้อมูลแบบ Tree ชนิดหนึ่งที่ใช้กันเยอะใน Blockchain) ส่วนผลลัพธ์ที่ได้จาก Execution ก็จะถูกส่งกลับไปที่ Consensus component ด้วย
11) Consensus component จะทำการเอาผลลัพธ์ส่งไปให้ Validator Nodes ตัวอื่น ๆ ยืนยันด้วยว่าได้ผลลัพธ์ตรงกันมั้ย
12) ถ้า Validator Nodes ส่วนใหญ่ (มากกว่า 2 ใน 3) ส่งตอบกลับมาว่ายอมรับพร้อมประทับตรา (Sign) ตัว V1 ก็จะเอา Transactions ทั้งหมดใน Block นั้นไปใส่ใน Persistant Storage เป็นอันเรียบร้อย
13) ปลายทางได้รับเงิน ต้นทางโดนตัดเงิน และ Sequence Number ของต้นทางจะเพิ่มขึ้นหนึ่ง ซึ่ง Sequence Number คือจำนวนการส่งที่ Address นั้น ๆ เคยส่ง (รับไม่นับ) ซึ่งนอกจากจะทำให้รู้แล้วว่าเราเคยส่งเงินไปกี่ครั้ง ตัวเลขตรงนี้ยังเอาไว้ใช้ป้องกันการ Replay ได้อีกด้วย
เนื้อหามาจากตรงเน้ Life of a transaction ไปอ่านกันดูล่าย
ใครบ้างอยู่ในกลุ่ม Partners
สำหรับกลุ่ม Partners ก็มีแต่ตัวเป้ง ๆ ทั้งนั้น Facebook, Mastercard, VISA, PayPal, eBay และอีกเยอะมาก ดูในรูปเลย แบบ ตัวใหญ่ ๆ มาหมดอ่ะ
ซึ่งแต่ละเจ้าก็คงมี Node ของตัวเองวางเพื่อขับเคลื่อน Libra Network นี้ให้ทำงานได้ ทาง Libra Association คาดหวังว่าจะมี Partners ร่วมด้วยถึง 100 เจ้าตอนที่เริ่มต้นใช้งานจริงในต้นปี 2020
จากโครงสร้างแล้ว จะบอกว่าเป็น Decentralized ก็คงไม่เต็มปากนักเพราะมีแต่ผู้เล่นรายใหญ่ที่เข้ามากุมอำนาจได้ ถึงแต่ละคนจะมีอำนาจน้อยนิดก็ตาม แต่เราไม่มีเลยไง 555 ศึกนี้เหมือนการพยายามสู้กันของระบบการเงินโลกใหม่กับโลกเก่ามากกว่า
ส่วนตัวเล็ก ๆ ก็เป็นผู้ใช้งานกันต่อปายยยย
แต่ก็อย่างว่าแหละ ถ้าต้องการ Blockchain ที่ใช้งานได้จริง สเกลได้เยอะจริง ก็ต้องไปทาง Centralized หน่อย ๆ ไม่งั้นไปไม่รอด =)
อยากเป็น Partner หรอ ? ไม่ยาก เอาเงินไปลง $10MM สิ !
สำหรับใครที่อยากเป็น Partner ก็ไม่ยากครับ แบกเงิน 10 ล้านเหรียญสหรัฐ ฯ ไปลงทุนก็ได้เป็น Partner แว้ววว วาง Node ได้ด้วยนะ เอาเลย ๆ
เตรียมลงแอป ฯ ของ Facebook ทั้ง Messenger, Whatsapp และ Instagram
แน่นอนว่าเป็นพระเจ้าในโลกอินเทอร์เนตขนาดนี้แล้ว จะเป็น Early Adopter เองก็คงไม่แปลก ทาง Facebook เลยวางแผน Integrate ฟีเจอร์ของ Calibra (คือแอป ฯ กระเป๋าตังค์ ไม่ใช่ตัว Libra ตรง ๆ) เพื่อให้ใช้งานผ่าน Messenger, Whatsapp และ Instagram ได้เลย !
หลัก ๆ ก็คือต้องสมัครแอคเค้าท์ของ Calibra ก่อน (แน่นอนต้อง KYC) แล้วถึงจะทำธุรกรรมผ่านแอป ฯ ที่ว่ามาได้ครับ
เขียน Smart Contract ด้วยภาษา Move
แน่นอนว่าขวบปีนี้แล้ว Blockchain ที่รัน Smart Contract ไม่ได้นี่มันเอ้าท์ไปแล้ว ไม่ต้องแปลกใจ Libra ก็เป็น Blockchain ที่สามารถรัน Smart Contract ได้เหมือนกันจ้า
ก็แสดงความยินดีสำหรับคนที่เขียน Solidity คล่องแล้วเพราะว่า ... ต้องศึกษาใหม่อยู่ดีจ้าาา คนละภาษากัน !!! 555 โดยภาษาที่จะใช้เขียน Smart Contract บน Libra มีชื่อว่า Move แต่โครงสร้างหน้าตาก็ลอก Solidity มาแหละ ซึ่ง Move นี่ยังคงอยู่ระหว่างการพัฒนา ตอนนี้ก็มีให้ดูคร่าว ๆ ก็คือ Move IR ที่เป็นภาษากึ่ง High Level กึ่ง Low Level มนุษย์อ่านออกด้วย คอมไพล์ด้วยตาได้ด้วยเพราะมีภาษาต่างดาวโผล่มาอยู่บ้าง
// The module for the account resource that governs every Libra account
module LibraAccount {
import 0x0.LibraCoin;
import 0x00.Hash;
// Every Libra account has a LibraLibraAccount.T resource
resource T {
// The coins stored in this account
balance: R#LibraCoin.T,
// The current authentication key.
// This can be different than the key used to create the account
authentication_key: bytearray,
// The current sequence number.
// Incremented by one each time a transaction is submitted
sequence_number: u64,
// TEMPORARY the current count for the number of sent events for this account
// The events system is being overhauled and this will be replaced
sent_events_count: u64,
// TEMPORARY the current count for the number of received events for this account
// The events system is being overhauled and this will be replaced
received_events_count: u64
}
// Message for sent events
struct SentPaymentEvent {
// The address that was paid
payee: address,
// The amount of LibraCoin.T sent
amount: u64,
}
// Message for received events
struct ReceivedPaymentEvent {
// The address that sent the coin
payer: address,
// The amount of LibraCoin.T received
amount: u64,
}
// Creates a new LibraLibraAccount.T
// Invoked by the `create_account` builtin
make(auth_key: bytearray): R#Self.T {
let zero_balance: R#LibraCoin.T;
zero_balance = LibraCoin.zero();
return T {
balance: move(zero_balance),
authentication_key: move(auth_key),
sequence_number: 0,
sent_events_count: 0,
received_events_count: 0,
};
}
// Deposits the `to_deposit` coin into the `payee`'s account
public deposit(payee: address, to_deposit: R#LibraCoin.T) {
let deposit_value: u64;
let payee_account_ref: &mut R#Self.T;
let sender: address;
let sender_account_ref: &mut R#Self.T;
let sent_event: V#Self.SentPaymentEvent;
let received_event: V#Self.ReceivedPaymentEvent;
// Check that the `to_deposit` coin is non-zero
deposit_value = LibraCoin.value(&to_deposit);
assert(copy(deposit_value) > 0, 7);
// Load the sender's account
sender = get_txn_sender();
sender_account_ref = borrow_global<T>(copy(sender));
// Log a send event
sent_event = SentPaymentEvent { payee: copy(payee), amount: copy(deposit_value) };
// TEMPORARY The events system is being overhauled and this will be replaced by something
// more principled in the future
emit_event(&mut move(sender_account_ref).sent_events_count, b"73656E745F6576656E74735F636F756E74", move(sent_event));
// Load the payee's account
payee_account_ref = borrow_global<T>(move(payee));
// Deposit the `to_deposit` coin
LibraCoin.deposit(&mut copy(payee_account_ref).balance, move(to_deposit));
// Log a received event
received_event = ReceivedPaymentEvent { payer: move(sender), amount: move(deposit_value) };
// TEMPORARY The events system is being overhauled and this will be replaced by something
// more principled in the future
emit_event(&mut move(payee_account_ref).received_events_count, b"72656365697665645F6576656E74735F636F756E74", move(received_event));
return;
}
// mint_to_address can only be called by accounts with MintCapability (see LibraCoin)
// and those account will be charged for gas. If those account don't have enough gas to pay
// for the transaction cost they will fail minting.
// However those account can also mint to themselves so that is a decent workaround
public mint_to_address(payee: address, amount: u64) {
let mint_capability_ref: &R#LibraCoin.MintCapability;
let coin: R#LibraCoin.T;
let payee_account_ref: &mut R#Self.T;
let payee_exists: bool;
let sender: address;
// Mint the coin
mint_capability_ref = LibraCoin.borrow_sender_mint_capability();
coin = LibraCoin.mint(copy(amount), move(mint_capability_ref));
// Create an account if it does not exist
payee_exists = exists<T>(copy(payee));
if (!move(payee_exists)) {
sender = get_txn_sender();
Self.create_new_account(copy(payee), 0);
}
// Load the `payee`'s account and deposit the minted `coin`
payee_account_ref = borrow_global<T>(move(payee));
LibraCoin.deposit(&mut move(payee_account_ref).balance, move(coin));
return;
}
// Helper to withdraw `amount` from the given `account` and return the resulting LibraCoin.T
withdraw_from_account(account: &mut R#Self.T, amount: u64): R#LibraCoin.T {
let to_withdraw: R#LibraCoin.T;
to_withdraw = LibraCoin.withdraw(&mut move(account).balance, copy(amount));
return move(to_withdraw);
}
// Withdraw `amount` LibraCoin.T from the transaction sender's account
public withdraw_from_sender(amount: u64): R#LibraCoin.T {
let sender: address;
let sender_account: &mut R#Self.T;
let to_withdraw: R#LibraCoin.T;
// Load the sender
sender = get_txn_sender();
sender_account = borrow_global<T>(move(sender));
// Withdraw the coin
to_withdraw = Self.withdraw_from_account(move(sender_account), move(amount));
return move(to_withdraw);
}
// Withdraw `amount` LibraCoin.T from the transaction sender's account and send the coin
// to the `payee` address
// Creates the `payee` account if it does not exist
public pay_from_sender(payee: address, amount: u64) {
let to_pay: R#LibraCoin.T;
let payee_exists: bool;
payee_exists = exists<T>(copy(payee));
if (move(payee_exists)) {
to_pay = Self.withdraw_from_sender(move(amount));
Self.deposit(move(payee), move(to_pay));
} else {
Self.create_new_account(move(payee), move(amount));
}
return;
}
// Rotate the transaction sender's authentication key
// The new key will be used for signing future transactions
public rotate_authentication_key(new_authentication_key: bytearray) {
let sender: address;
let sender_account: &mut R#Self.T;
sender = get_txn_sender();
sender_account = borrow_global<T>(move(sender));
*(&mut move(sender_account).authentication_key) = move(new_authentication_key);
return;
}
// Creates a new account at `fresh_address` with the `initial_balance` deducted from the
// transaction sender's account
public create_new_account(fresh_address: address, initial_balance: u64) {
create_account(copy(fresh_address));
if (copy(initial_balance) > 0) {
Self.pay_from_sender(move(fresh_address), move(initial_balance));
}
return;
}
// Helper to return u64 value of the `balance` field for given `account`
balance_for_account(account: &R#Self.T): u64 {
let balance_value: u64;
balance_value = LibraCoin.value(&move(account).balance);
return move(balance_value);
}
// Return the current balance of the LibraCoin.T in LibraLibraAccount.T at `addr`
public balance(addr: address): u64 {
let payee_account: &mut R#Self.T;
let imm_payee_account: &R#Self.T;
let balance_amount: u64;
payee_account = borrow_global<T>(move(addr));
imm_payee_account = freeze(move(payee_account));
balance_amount = Self.balance_for_account(move(imm_payee_account));
return move(balance_amount);
}
// Helper to return the sequence number field for given `account`
sequence_number_for_account(account: &R#Self.T): u64 {
return *(&move(account).sequence_number);
}
// Return the current sequence number at `addr`
public sequence_number(addr: address): u64 {
let account_ref: &mut R#Self.T;
let imm_ref: &R#Self.T;
let sequence_number_value: u64;
account_ref = borrow_global<T>(move(addr));
imm_ref = freeze(move(account_ref));
sequence_number_value = Self.sequence_number_for_account(move(imm_ref));
return move(sequence_number_value);
}
// Checks if an account exists at `check_addr`
public exists(check_addr: address): bool {
let is_present: bool;
is_present = exists<T>(move(check_addr));
return move(is_present);
}
// The prologue is invoked at the beginning of every transaction
// It verifies:
// - The account's auth key matches the transaction's public key
// - That the account has enough balance to pay for all of the gas
// - That the sequence number matches the transaction's sequence key
prologue() {
let transaction_sender: address;
let transaction_sender_exists: bool;
let sender_account: &mut R#Self.T;
let imm_sender_account: &R#Self.T;
let sender_public_key: bytearray;
let public_key_hash: bytearray;
let gas_price: u64;
let gas_units: u64;
let gas_fee: u64;
let balance_amount: u64;
let sequence_number_value: u64;
let transaction_sequence_number_value: u64;
transaction_sender = get_txn_sender();
// FUTURE: Make these error codes sequential
// Verify that the transaction sender's account exists
transaction_sender_exists = exists<T>(copy(transaction_sender));
assert(move(transaction_sender_exists), 5);
// Load the transaction sender's account
sender_account = borrow_global<T>(copy(transaction_sender));
// Check that the transaction's public key matches the account's current auth key
sender_public_key = get_txn_public_key();
public_key_hash = Hash.sha3_256(move(sender_public_key));
assert(move(public_key_hash) == *(©(sender_account).authentication_key), 2);
// Check that the account has enough balance for all of the gas
gas_price = get_txn_gas_unit_price();
gas_units = get_txn_max_gas_units();
gas_fee = move(gas_price) * move(gas_units);
imm_sender_account = freeze(copy(sender_account));
balance_amount = Self.balance_for_account(move(imm_sender_account));
assert(move(balance_amount) >= move(gas_fee), 6);
// Check that the transaction sequence number matches the sequence number of the account
sequence_number_value = *(&mut move(sender_account).sequence_number);
transaction_sequence_number_value = get_txn_sequence_number();
assert(copy(transaction_sequence_number_value) >= copy(sequence_number_value), 3);
assert(move(transaction_sequence_number_value) == move(sequence_number_value), 4);
return;
}
// The epilogue is invoked at the end of transactions.
// It collects gas and bumps the sequence number
epilogue() {
let transaction_sender: address;
let sender_account: &mut R#Self.T;
let imm_sender_account: &R#Self.T;
let gas_price: u64;
let gas_units_remaining: u64;
let starting_gas_units: u64;
let gas_fee_amount: u64;
let balance_amount: u64;
let gas_fee: R#LibraCoin.T;
let transaction_sequence_number_value: u64;
transaction_sender = get_txn_sender();
// Load the transaction sender's account
sender_account = borrow_global<T>(copy(transaction_sender));
// Charge for gas
gas_price = get_txn_gas_unit_price();
starting_gas_units = get_txn_max_gas_units();
gas_units_remaining = get_gas_remaining();
gas_fee_amount = move(gas_price) * (move(starting_gas_units) - move(gas_units_remaining));
imm_sender_account = freeze(copy(sender_account));
balance_amount = Self.balance_for_account(move(imm_sender_account));
assert(move(balance_amount) >= copy(gas_fee_amount), 6);
gas_fee = Self.withdraw_from_account(copy(sender_account), move(gas_fee_amount));
LibraCoin.TODO_REMOVE_burn_gas_fee(move(gas_fee));
// Bump the sequence number
transaction_sequence_number_value = get_txn_sequence_number();
*(&mut move(sender_account).sequence_number) = move(transaction_sequence_number_value) + 1;
return;
}
}
หรือเอาแบบง่าย ๆ อันนี้เป็นโค้ดสำหรับการโอนเหรียญ LibraCoin
public main(payee: address, amount: u64) {
let coin: 0x0.Currency.Coin = 0x0.Currency.withdraw_from_sender(copy(amount));
0x0.Currency.deposit(copy(payee), move(coin));
}
สั้น ๆ แค่นี้แหละ เค้าเตรียม Library มาพร้อมหมดแล้ว
หรือจะสร้างเหรียญเองก็ทำ module
ขึ้นมาว่า
module Currency {
resource Coin { value: u64 }
// ...
}
ส่วนคำสั่งต่าง ๆ ข้างในนี่หน้าตาเหมือน ERC-20 เลย ต้องเขียนลอจิคการโอนและตรวจสอบสิ่งต่าง ๆ เองเพื่อให้ถูกคุณลักษณะของเหรียญที่เราจะสร้างขึ้นมา ลอกกันมาแน่นวล ไม่พูดถึงละกันนะ (เอาจริง ๆ เราแอบเกลียดการสร้างเหรียญได้เอง มันน่าเบื่อและไร้ประโยชชชชชน์)
สำหรับ Move ก็เหมือน Solidity ก่อนจะรันได้ต้องคอมไพล์เป็น Move Bytecode และ Deploy ขึ้น Blockchain ก่อน (จริง ๆ ใน Paper เค้าบอกจะเขียนเป็น Bytecode เลยก็ได้นะ แต่เค้าไม่ได้เอามาให้ดูเพราะบอกว่าน่าจะอ่านกันไม่ออก ... จ้าาาา)
ใครอยากเขียน Move และคอมไพล์เล่น เชิญที่ Libra Compiler ได้เลยจ้าาา เล่นมาละ สนุกดี
Testnet มีให้เล่นแล้ว
คนจริงต้องเปิดตัวพร้อม Testnet ฮะ นี่ก็เลยมี Testnet ให้เล่นแล้ว ง่ายมาก ๆ แค่สามคำสั่ง
$ git clone https://github.com/libra/libra.git && cd libra
$ ./scripts/dev_setup.sh
$ ./scripts/cli/start_cli_testnet.sh
จากนั้นรอโหลดแป๊บนึงแล้วจะขึ้นเป็น Console ให้เล่นกัน มีคำสั่งให้เล่นอยู่จำนวนหนึ่ง ลองไปทำตามในนี้ได้ My First Transaction
อย่างอันนี้ลองสร้างกระเป๋าไว้สองใบ แอบพิมพ์เงินมาเล่น แล้วก็โอนเงินหากันดู ผลคือ ... แค่ 2 วิก็เสร็จแล้วววว ไวมากกกกก อันนี้เป็น Testnet จริงแล้วนะ ไม่ใช่รันในเครื่องตัวเอง
อย่างไรก็ตาม ย้ำอีกทีว่าตามสเปคจะต้องรอ 10 วิกว่าทุกอย่างจะยืนยันเสร็จนะครับ ถึงจะเห็นว่าเร็วแต่ถ้าพัฒนาอะไรก็ต้องเผื่อเวลาไว้นิดนึง
ใครอยากเล่นเชิญเว็บ Libra Developers โลด ! นอกจากจะเล่นกับ Testnet ได้แล้วยังเป็น Local Network ของตัวเองได้ด้วย มัน Open Source ใครอยากทำโปรเจคของตัวเองด้วย Libra ก็ได้เลย (แต่แนะนำให้รอมัน Stable กว่านี้ก่อนก็ดี ภาษา Move ยังไม่ไปถึงไหนเลย)
โดนแฮคหรอ โดน Scam หรอ ไม่เป็น Calibra Refund ให้ได้นะ ~~~
พอเป็น Blockchain ที่ทุกคนจะต้องดูแลทรัพย์สินและกระเป๋าตังค์ของตัวเอง ถ้าหายก็หายเลย หมดตัวก็หมดเลย ไม่มีใครช่วยอะไรได้ อย่างที่เคย ๆ เห็นข่าวมาว่าลืมกุญแจเปิดกระเป๋าทำให้เงินหายไปหมดเข้าถึงไม่ได้อยู่บ่อย ๆ นั่นแหละ
จุดอ่อนใหญ่ ๆ ของ Blockchain คือมัน Geek พอจะเข้าสู่กลุ่มแมสซึ่งไม่ได้เชี่ยวชาญด้านเทค ฯ มาก คนก็จะลืมโน่นลืมนี่ทำโน่นทำนี่หายอยู่ตลอดเวลา ถ้าเป็นธนาคารก็มีคนช่วยได้ โดนโกงก็ร้องเรียนได้ บลา ๆ ๆ แต่ Blockchain นี่คือไม่ได้เลยนะ
สำหรับ Libra จริง ๆ โดยพื้นฐานก็เป็นแบบนั้น ทุกอย่างที่เกิดขึ้นไม่สามารถ Reverse ได้ แต่ ... Facebook ก็คิดจุดอ่อนนี้ไว้แล้ว ก็เลยออกแบบตัวกระเป๋าตังค์ Calibra มาเพื่อรองรับกรณีแบบนี้
1) ถ้าลืม Password เข้าถึงกระเป๋า ทาง Facebook ช่วยได้
2) ถ้าโดนแฮค มีคนเข้ากระเป๋าเราโดยเราไม่รู้ ทาง Facebook จะ Refund เงินให้เรา
ถามว่าทำได้ยังไง ? มันไม่ได้ไป Reverse Transaction ใน Libra หรอก แต่เค้าช่วยรับผิดชอบให้เฉย ๆ ด้วยการส่งเงินมาให้เรา ส่วนเงินที่เสียไปจากการโดนแฮคนี่ก็ไม่รู้เหมือนกันว่าเค้าจะทำยังไงต่อ อาจจะไม่สนใจมากก็ได้มั้ง เงินเหลือเยอะ
หนึ่งสิ่งที่ยังไม่มั่นใจคือ Calibra เป็นแค่ Wallet หรือเป็น Layer 2 กันแน่ ยังไงคงต้องรอข้อมูลมากกว่านี้ก่อนครับแล้วอาจจะเข้าใจ Mechanic มากกว่านี้
มีอีกหลายอุปสรรคให้ Libra ก้าวผ่าน
ถึง Libra จะเกิดมาอย่างสง่างาม ถูกแบคด้วยบริษัทใหญ่ ๆ มากมาย ออกแบบมาเพื่อให้ใช้งานจริงไม่ได้เพื่อหลอกลวงผู้บริโภคไปวัน ๆ แต่เนื่องจากมันเป็นเรื่องของการเงินที่กระทบความมั่นคงของประเทศหลาย ๆ ประเทศ อนาคตของ Libra จึงอาจจะไม่ได้ราบรื่นมากนัก คงมีอุปสรรคมากมายให้พานพบระหว่างทาง
เชื่อสิว่าเดือนนี้น่าจะมีข่าวประเทศโน้นประเทศนี้แบนกันให้เพียบ ก็รอติดตามกันดูดี ๆ
และเอาจริง ๆ ถามว่า Libra เป็นเหรียญแบบ Decentralized ที่ประชาชนทุกคนพร้อมใจกันสร้างขึ้นมาใช้มั้ย ก็ไม่ใช่ มันเป็นสินทรัพย์ที่ถูกสร้างด้วยเศรษฐีจำนวนหนึ่งเพื่อให้เราเอามาเป็นต้วกลางซื้อขายสิ่งของเท่านั้นเอง และสุดท้ายก็จะหาประโยชน์จากมันอยู่ดี
ตอนนี้มี 27 รายที่เป็น Partners ก็แปลว่าเงินทั้งหมดถูกกุมชะตาด้วยคน 27 คนทั่วโลกนะ ต่อให้เพิ่มเป็น 100 ราย ก็แปลว่าเงินมหาศาลในมือทุกคนถูกกุมชะตาด้วยคนแค่ 100 คนเองนะเฮ้ย !
มีอะไรต้องพิสูจน์ตัวเองอีกเยอะครับ ส่วนเราในฐานะนักพัฒนาก็ต้องติดตามกันไป
ส่วนในฐานะผู้ใช้ ... ศึกษาให้ดี ศึกษาให้เยอะ ๆ ก่อน จะได้ไม่เจ็บตัวทีหลังเนอะ =)