หลังจากเราเริ่มทำระบบ Blockchain จนสามารถสร้าง Block / Transaction และระบบ Wallet ได้แล้ว เราจะมาทำระบบ Proof of Work กัน เพื่อใช้ยืนยันในการสร้าง Block ของตัว Blockchain
Why Proof of Work?
Proof of Work นั้นเกิดมาเพื่อให้การสร้างข้อมูลบน Blockchain นั้นทำได้ยากและต้องแลกมาด้วยอะไรสักอย่างเพื่อพิสูจน์ตนเอง เช่นใช้พลังงานในการคำนวนหาค่า Hash ของ Block ซึ่งเป็นการคำนวนทางคณิตศาสตร์วนซ้ำไปซ้ำมาเรื่อยๆจนกว่าจะได้ค่าที่ถูกต้อง ดังนั้นคนที่สามารถยืนยันข้อมูลนั้นได้จึงต้องมีพลังประมวลผลที่สูงมากที่จะคำนวนหาค่านั้นได้ก่อนคนอื่น ซึ่งก็แลกมาด้วยเงินลงทุน พลังงานไฟฟ้าที่ใช้เป็นต้น และเมื่อคนนั้นยืนยันได้ ก็จะได้รางวัลเป็นผลตอบแทนไป
เมื่อมีเงินรางวัลก็จะเกิดการแข่งขันกันเพื่อยืนยันข้อมูล ระบบจึงดูน่าเชื่อถือขึ้น เพราะการสร้าง Block นั้นก็จะไม่ได้ขึ้นอยู่กับคนใดคนหนึ่ง เช่น Block นี้สร้างโดย A ไม่ได้หมายความว่า Block ถัดไปจะถูกสร้างโดย A ทำให้ความเป็นไปได้ที่คนใดคนหนึ่งจะเป็นผู้ควบคุมระบบนั้นน้อยมาก
แต่ในบางครั้ง Proof of work นั้นก็ไม่จำเป็นต้องแข่งขันละมีรางวัลให้คนขุดเสมอไป เช่น ระบบที่ใช้กันภายใน ( Private Blockchain ) เราถือว่าคนในระบบนั้นมีความน่าเชื่อถือ สามารถใช้แค่ Node เดียวทำการยืนยันข้อมูลไปเลยก็ยังได้ รวมถึงสามารถปรับความยากให้การยืนยันข้อมูลให้ลงมาต่ำได้กว่าระดับปกติ เพื่อแลกกับความรวดเร็วในการประมวลผลแทน
Attacker Problem
แต่ยังไม่ได้หมายความว่าระบบ Blockchain นั้นปลอดภัย 100% นะครับ เพราะในขั้นตอนการทำ Proof of Work ก็ยังมีช่องโหว่ให้ผู้ไม่หวังดีนั้นสามารถที่จะเข้ามาโจมตีระบบได้อยู่ดี โดยเฉพาะกรณีที่ผู้ไม่หวังดีนั้น มีกำลังในการขุดมากๆ เกินกว่าครึ่งหนึ่งของกำลังในระบบ โดยจะทำให้ผู้ไม่หวังดีอาจจะกลายเป็นคนเดียวที่ยืนยันข้อมูลในระบบได้เลย ซึ่งใน Public Blockchain นั้นไม่ใช่เรื่องดีแน่นอน หากคนนั้นนำพลังอำนาจไปใช้ในทางที่ผิด เราเรียกการโจมตีแบบนี้ว่า “51% Attack” ซึ่งอาจจะเกิดปัญหาตามมาได้ เช่น
- เลือกที่จะไม่ยืนยัน Transaction ได้ ในกรณีนี้อาจจะทำให้ Transaction ของเราไม่สามารถถูก Confirm ได้เลยในระบบ แล้วเราก็ทำอะไรไม่ได้ เพราะไม่มีคนอื่นมาช่วยในการยืนยัน Transaction ของเรา
- Double Spent หรือมีการนำ Transaction เก่าๆที่เคยถูกใช้ไปแล้วกลับมาใช้ใหม่ได้ ทำให้เงินในระบบไม่มีความหมายไปเลย
How it Work?
ทบทวนกันอีกรอบว่า Proof of work นั้นมีวิธีการอย่างไร การสร้าง Block แต่ละครั้งนั้น จะใช้วิธีการ Hash ข้อมูลที่อยู่ใน Block ออกมาเพื่อนำมาใช้เป็น ID ของ Block นั้นใช่ไหมครับ
Hash เนี่ยจริงๆมันเป็นการเข้ารหัสทางเดียว โดยค่าที่ออกมานั้น หาก Hash ด้วยข้อมูลเหมือนกัน ยังไงผลลัพธ์ย่อมออกมาเหมือนกัน เพียงแค่เราไม่สามารถย้อนกลับไปเป็นข้อมูลเดิมได้ และจากที่ตัวมันเป็นการคำนวนทางคณิตศาสตร์ ทำให้ผลที่ได้นั้นออกมาในรูปแบบของตัวเลข ซึ่งส่วนใหญ่จะใช้เป็นเลขฐาน 16 (Hex) เนื่องจากดูง่ายที่สุด
เมื่อเราได้ผลลัพธ์ออกมาแล้ว ขั้นตอนถัดมาคือการกำหนดค่า Hex ที่ได้ออกมานั้น เราจะให้มันเป็นค่าที่ถูกต้องหรือไม่ โดยการกำหนดว่าที่ได้นั้น น้อยกว่าค่าเป้าหมายหรือเปล่า เช่น ค่าที่ได้ต้องน้อยกว่า 1+E61 เป็นต้น
แล้วจะทำยังไงให้ได้ค่าที่ต้องการละ ใน Hash ค่าเดิมแล้วผลลัพธ์มันได้เหมือนเดิม ง่ายเราก็ใส่ Nonce ลงไปเพื่อให้ค่ามันเปลี่ยน จนนั้นก็ Brute Force ไปเรื่อยๆจนกว่าจะได้ผลลัพธ์ที่ต้องการ
ค่าเป้าหมายที่เราต้องไว้ยังเป็นตัวกำหนดความยากง่ายในการหาค่าที่ถูกต้องอีกด้วย หากเรากำหนดไว้ต่ำ ความยากในการค้นหาก็จะมากขึ้น ใช้เวลาในการคำนวนมากขึ้น ใน Public Blockchain นั้นจึงกำหนดความยากไว้ในระดับหนึ่ง คนที่จะเข้ามาขุดจึงต้องแลกมาด้วยการลงทุนในอุปกรณ์ ค่าไฟฟ้ามาก เพื่อให้ได้รับรางวัลในการขุดมา
ส่วนในระบบ Private Blockchain นั้นไม่จำเป็นที่จะทำกำหนดความยากไว้สูงก็ได้ เนื่องจากใช้ความน่าเชื่อถือภายในแทน แถมช่วยให้การยืนยันข้อมูลได้รวดเร็วกว่าด้วย
Let’s Coding
มาเริ่มทำระบบ Proof Of Work กันดีกว่า เริ่มนำข้อมูลภายใน Block จากเดิมที่จะมาทำฟังก์ชัน Hash โดยจะใช้ library big-integer
เข้ามาช่วยในการตรวจสอบว่า Hash ที่ออกมานั้นใช่ค่าที่ถูกต้องหรือยัง
เราสามารถกำหนดค่าความแยกของการทำ Proof Of Work ได้จากค่า target
โดยยิ่งน้อยก็จะยิ่งยากและใช้เวลานานขึ้น (หรืออาจหาไม่ได้เลย) จากนั้นเมื่อได้ค่า Hash ที่ต้องการแล้วก็ส่งค่า Hash และ Nonce ที่ได้กลับไปเพื่อบันทึกลง Block
เปลี่ยนฟังก์ชัน mine
เดิมจากที่เราเคยตั้งค่า Hash ให้มันตรงๆ ไปเรียกใช้ Proof Of Work เพื่อหาค่า Hash แทน
แก้ไขฟังก์ชัน init
ตอนสร้าง Genesis Block ด้วย
แก้โครงสร้างของ Block ให้บันทึก Nonce เข้าไปด้วย
เรียบร้อย
Testing
ทดสอบการสร้าง Block ใหม่ด้วย Proof Of Work นะครับ เราก็จะได้ค่า Hash ค่า Nonce มาครับ โดยใช้เวลาสร้าง Block เฉลี่ย ประมาน 300ms
ทดลองเปลี่ยนค่า complex ให้ยากขึ้นกว่าเดิมก็จะพบว่าใช้เวลาในการสร้าง Block นานขึ้นนั่นเอง (complex = 18) โดยใช้เวลากว่า 10s เลยทีเดียว