Blockchain EP.1 : Simple Blockchain Prototype in Node.js
เมื่อเข้าใจ Concept ในตอนที่แล้วกันแล้ว คราวนี้เราจะมาเรียนรู้ด้วยการ Implement Prototype ขึ้นมากันจริงๆนะครับ โดยในตัวอย่างจะเขียนบน Node.js นะครับ สำหรับใครที่ยังไม่เคยเขียนอาจจะเขียนตามไปด้วยภาษาที่ท่านถนัดได้เลย
ดูโค้ดตัวเต็มได้ที่นี่ >> Github
Blockchain Structure
ตัว Blockchain เองนั้นเป็นแค่การเก็บข้อมูลลงในฐานข้อมูล และมีข้อมูลที่บอกการเชื่อมโยงไปยังข้อมูลก่อนหน้านี้เท่านั้นเองครับ มันคือ Linked-List นั่นเอง ดังนั้นตัวโครงสร้างในโค้ด จึงเป็นการดึงข้อมูลมาจาก Database ซะส่วนใหญ่
หน้าที่ของ Blockchain ในโค้ดจึงเป็นการ
- สร้าง Genesis Block เพื่อเริ่มต้น Blockchain
- รับข้อมูลและทำประมวลผลการสร้าง Block ใหม่
- บันทึกและดึงข้อมูลของ Block และ Hash ของ Block ล่าสุด จาก Database
โดยในตัวอย่างจะใช้เป็น Document-Base DB ชื่อ nedb นะครับ เนื่องจากสามารถใช้ง่ายและบันทึกลงเป็นไฟล์ได้เลย ไม่ต้องเสียเวลา Setup DB เพิ่ม
คลาส Blockchain ของเราจึงมีตัวแปรอยู่ 2 ตัว คือตัว DB และ Hash ของ Block ล่าสุดและเนื่องจากตัว nedb เป็น Document-Base DB และไม่ได้มีการแบ่ง Table เราจะจำเป็นต้องเก็บแยกโดย db.blockchain จะใช้เก็บ Record ของแต่ละ Block และ db.latestHash ใช้เก็บแค่ค่า Hash ของ Block ล่าสุดเท่านั้น
Block Structure
ในส่วนของ Block แต่ละตัวนั้น ก็จะเก็บข้อมูลง่ายๆ 4 ตัวด้วยกันคือ
- Timestamp เวลาของ Block นั้น
- Data คือข้อมูลที่เราจะใส่ลงไป
- Hash เกิดจากการเอาค่าใน Block นั้นไปเข้าฟังก์ชัน Hash ด้วยอัลกอริทึมใดๆ เช่น SHA-256 เพื่อใช้เป็น ID ของ Block
- PrevBlockHash เก็บไว้เพื่อระบุว่า Block นี้ต่อมาจาก Block ไหน
และฟังก์ชันสำหรับสร้าง Hash ของ Block นั้น
** จริงๆขั้นตอนการสร้าง Hash ของ Block จะอยู่ในการทำ Proof of Work และไม่ได้ Hash ตรงๆแบบนี้ ซึ่งเราจะแก้และอธิบายในส่วนของ EP. Proof of Work อีกทีนะครับ
Create a New Block
เมื่อได้โครงสร้างของ Block แล้ว ถัดมาเราจะมาสร้างฟังก์ชันที่ใช้สำหรับสร้าง Block โดยดึง Timestamp ล่าสุดและนำข้อมูลที่ผู้ใช้กรอกมา มาสร้างเป็น Block ใหม่ครับ
Genesis Block
จุดเริ่มต้น Blockchain เริ่มที่ Block แรกในสายโซ่ของระบบ ฺBlockchain โดยเราเรียกมันว่า Genesis ฺBlock โดยเบื้องต้นเรากำหนดข้อมูลอะไรก็ได้ลงไปใน Genesis Block ได้เลยครับ
Build a Blockchain Function
ฟังก์ชันหลักๆใน Blockchain ก็จะประกอบไปด้วยการดึงข้อมูลจาก DB ครับ
Blockchain Iterator
ทีนี้เรามาสร้าง Class ที่จะใช้สำหรับสำรวจ Block ต่างๆในสาย Blockchain กันครับ โดยฟังก์ชันหลัก คือการหา Block ถัดไปจาก Hash เริ่มต้นนั่นเอง
Mining a new Block
ฟังก์ชันสำคัญของ Blockchain คือการสร้าง Block ใหม่ โดยนำข้อมูลมาสร้างเป็น Block ต่อจาก Block ล่าสุดของระบบและบันทึกลง DB
Interface
จากนั้นเราจะมาทำ Interface ของการเข้าใช้งาน Blockchain ของเรากัน โดยจะให้เข้าใช้งานผ่าน Command-Line Interface นะครับ ผมใช้ Library ที่ชื่อว่า vorpal
ในการเขียน โดยแบ่งออกเป็น Cmd ดังนั้น
- init
สำหรับสร้างสาย blockchain ใหม่พร้อม Genesis block กรณีที่ยังไม่มีการสร้าง Blockchain ขึ้นมา
- blockchain list
สำหรับดึงรายการทั้งหมดใน Blockchain โดยดึงเอา Iterator มาเพื่อวนลูปดึงข้อมูลจาก Block ล่าสุดและไล่หากจาก Hash ลงไปเรื่อยๆจนเจอ Genesis Block
- blockchain insert -d “ข้อมูล”
สำหรับการสร้าง Block ใหม่เข้าไปใน Blockchain
ในส่วนของโค้ดตัวเต็มสามารถเข้าไปดู Gist ได้เลยนะครับ (ไม่ขออธิบายในส่วนนี้)
ในไฟล์ index.js
ขอโปรเจ็คหลักเราจึงเรียกใช้ Blockchain และ Command มาใช้ โดยดึงข้อมูล Blockchain และ Hash ล่าสุดมา และเรียกใช้งาน Command เพื่อเข้าสู่ In-app Command Interface
Testing
พอได้ Interface แล้วเราก็จะมาลองเรียกใช้งานกันดูนะครับ ( ใครที่งงวิธีการรัน แนะนำให้ไปดู github ตัวเต็มนะครับ) โดยรัน node index.js
เพิ่มเข้า In-app Interface กันก่อน
อันดับแรกคือการสร้าง Blockchain โดยคำสั่ง init
เพื่อให้ตัว Blockchain นั้นทำการสร้าง Genesis Block ขึ้นมา
ถัดมาก็ทดลองสร้าง Block ใหม่ด้วยคำสั่ง insert
จะเห็นได้ว่าผลรันที่ได้ในแต่ละ Block ก็จะเชื่อมโยงกับ Block ก่อนหน้านี้ด้วย Hash กันเป็นทอดๆไป
ทีนี้มาลองดึง Block ทั้งหมดที่มาใช้ Blockchain ของเรามา โดยใช้คำสั่ง list
โดยก็จะเรียงจาก Block ล่าสุดจากค่า LatestHash ที่บันทึกไว้ในฐานข้อมูล แล้วทำการวนหา Block ก่อนหน้านี้ด้วย Hash ลงไปเรื่อยๆจนถึง Genesis Block นะครับ
Conclusion
พื้นฐานของคำว่า Blockchain คือการเก็บข้อมูลของ Block และแต่ละ Block ข้อมูลเชื่อมต่อกัน บทความถัดไปจะพาเปลี่ยนส่วน Data ของ Block ให้เก็บการเก็บข้อมูล Transactions เพื่อช่วยให้กลายเป็นระบบที่สามารถโอนข้อมูลจาก A ไป B หรือ D ไป B ได้จริงๆ จากที่ในบทความนี้เราเก็บแค่ Text ธรรมดาเท่านั้น