โค้ด Full-stack Blockchain Test Network with Angular, NodeJs แบบบ้านๆ – EP1: Project Organisation and Architecting Back-end

Blockchain เป็น เทรนด์เทคโนโลยีที่มาแรงมากๆ เนื่องจาก concept ของ Blockchain เป็น อะไรที่ทำความเข้าใจได้ยาก โดยเฉพาะ คนที่ไม่ได้มากจากสาย tech เลยเป็นที่มาของ บล็อกนี้ครับ

ส่วนตัวเป็นคนที่อยากเรียนรู้อะไร ก็อยากที่จะเข้าใจใน topic นั้นจริงๆ และวิธีที่เร็วที่สุดสำหรับผมคือ การลองลงมือทำ Project จริงๆ โดยได้ลองเขียน Blockchain Network แบบง่ายๆขึ้นมาหนึ่งอัน ก็เลยถือโอกาสเขียนบล็อกเกี่ยวกับโปรเจคนี้ โดยโปรเจคนี้ได้แรงบันดาลใจมาจาก https://lhartikk.github.io/   และ https://github.com/15Dkatz/cryptochain ครับ

ในบล็อกนี้ ค่อนข้าง เทคนิคอลนิดหน่อย เพราะขอเน้นไปที่ส่วนของ coding และ Project Architecture โดยใน EP แรกจะขอเขียนถึง โครงสร้าง, logic และ Tools ที่ใช้ในการ implement ในส่วนของหลังบ้านก่อน และเนื่องจาก บล็อกนี้จะมีไว้เพื่อศึกษาหลักการทำงานของ Blockchain ดังนั้นจึงไม่ได้พิจารณาถึง security ต่างๆ จึงไม่แนะนำให้ใช้ใน production ยังต้องพัฒนาและแก้อีกเยอะหากจะนำไปใช้จริงครับ

สำหรับคนที่อ่านแล้วยังงงๆกับศัพท์ หรือ อยากเข้าใจ Blockchain ให้มากกว่านี้ ขอแนะนำ บล็อกของคุณหนูเนย ตามลิ้งค์ https://nuuneoi.com/blog/blog.php?read_id=900 เขียนได้เข้าใจง่ายมาก

ในบล็อกนี้จะขอเขียนถึง Logic เพื่อให้เห็นภาพรวมในแต่ละส่วนก่อน จากนั้นค่อยเจาะลึกไปที่ Coding

เพื่อนๆ สามารถ เข้าไปดู Source Code ที่ Github ของผม ที่ https://github.com/Ratimon/full-stack-blockchain-network 

Blockchain System Architecture: Introduction and Overview

ตัวอย่างที่โด่งดังและมีชื่อเสียงที่สุด ของ Blockchain network ก็คือ Bitcoin หรือ ระบบบัญชีธนาคารที่ คนในระบบสามารถส่ง value ถึงกันได้

ในบล็อกนี้จะกล่าวถึง Blockchain Network แบบเบสิคสุดๆ โดย คนในระบบสามารถส่งเงินถึงกันได้ โดย Network ควรประกอบไปด้วย Node จำนวนมาก ซึ่งประกอบไปด้วยส่วนต่างๆดังนี้:

Blockchain Architecture

1) Node

Blockchain Network ใช้ระบบแบบ peer-to-peer network (P2P)  ซึ่งก็คือระบบที่ไม่มีศูนย์กลาง พูดง่ายๆก็คือไม่มีคนที่มีอำนาจอย่างเต็มที่ในการควบคุม Network โดยทุกๆ Peer หรือ Node จะทำหน้าที่เพิ่ม, ยืนยัน,และ เก็บ ข้อมูลเป็นสำเนาชุดเดียวกัน

โดยประโยชน์ของระบบ แบบ P2P หรือ เรียกอีกอย่างว่า ระบบแบบ Decentralization มีดังนี้

  1. Immutability ข้อมูลจะไม่มีทางเปลี่ยนแปลง เนื่องจากทุกๆคนช่วยกันถือข้อมูลคนละชุด หากข้อมูลเปลี่ยน สำเนาของทุกคนจะถูกทุกคนในระบบช่วยกันตรวจสอบและยืนยัน หากไม่ตรงกับเสียงส่วนใหญ่ ข้อมูลจะไม่ถูกปลอมแปลง
  2. Fault tolerance หรือ ระบบล่มได้ยากกว่า เนื่องจาก ไม่มีตัวกลางที่ควบคุม Network ทุกคนจะช่วยกันรันระบบ ระบบจะไม่มีทางล่มหากยังมีคนอยู่ในระบบอยู่
  3. Attack Resistance ระบบถูกออกแบบให้ใช้ต้นทุนสูงกว่าปกติในการโจมตีระบบ โดยจริงๆแล้วใช้หลักของเศรษศาสตร์ในการแก้ปัญหา

Why Immutability? เบื้องหลังการทำงานของ Blockchain

ก่อนจะไปต่อกัน ต้องทำความเข้าใจกับคำศัพท์และนิยามเหล่านี้ก่อนครับ

Blockchain Network คือ peer-to-peer network (P2P) แบบหนึ่งที่เก็บข้อมูลเป็น Blockchain

Blockchain คือ Data Structure ชนิดหนึ่งที่เชื่อม Block หลายๆ Block กันด้วย Hash Function ตามรูป

credit: blockgeeks.com

จะสังเกตได้ว่าในแต่ละ Block จะมี ค่า hash ของข้อมูลทั้งหมดของ Block นั้นรวมกัน และจะมีค่า previousHash ซึ่งเป็นค่าเดียวกับค่า hash ของ Block ก่อนหน้านั้นๆ เป็น block ต่อกันไปเรื่อยๆ เรียกว่า Blockchain นั่นเอง

Hash คือ การเข้ารหัสทางเดียว ซึ่ง hash function ที่ดีควรมีคุณสมบัติดังนี้:

1. Deterministic ข้อมูลเดียวกันจะให้ค่า Hash เดียวกัน

2. Quick คำนวณ Hash ได้เร็ว

3. Collision Resistance คือ ค่า Hash ของข้อมูลที่ไม่เหมือนกันจะไม่มีทางเหมือนกัน เช่น ค่า Hash ของ “BLOCKCHAIN” จะไม่เหมือนกับ “blockchain”

4. Pre-image Resistance ไม่สามารถหาข้อมูลดั้งเดิมจาก hash ที่เกิดจาก ข้อมูลนั้น พูดง่ายๆคือ เมื่อ hash ไปแล้ว ไม่สามารถย้อนกลับนั่นเอง

5. Second Pre-image Resistance  ยากที่จะหาข้อความสองข้อความที่ไม่เหมือนกัน แต่ Hash ของทั้งสองข้อความมีค่าเหมือนกัน

เนื่องด้วยคุณสมบัติของ hash ทำให้เมื่อข้อมูลใดๆ ใน Block ถูกเปลี่ยนแปลง ค่า hash ก็จะถูกเปลียนแปลงตามไปด้วย หากมีใครพยายามที่จะปลอมแปลงข้อมูลภายใน Block ก่อนๆ ค่า Hash ก็จะไม่ตรงกับ previousHash ของ Block ต่อๆไป และจะส่งผลให้ Node อื่นๆสามารถตรวจสอบและปฎิเสธข้อมูลเหล่านั้นได้ ด้วยวิธีนี้ทำให้ข้อมูล มีความ immutability และ มีความปลอดภัยสูงขึ้น นั่นเอง

2) Miner 

เช่นเคยครับ ก่อนจะไปต่อ มาทำความเข้าใจกับนิยามและคำศัพท์ก่อนครับ

Why Fault tolerance? เบื้องหลังการทำงานของ Miner

อย่างที่ได้กล่าวไปว่า ระบบแบบกระจายศูนย์ จะไม่มีคนใดคนหนึ่งมีอำนาจในการควบคุมระบบอย่างเบ็ดเสร็จ แล้วใครจะเป็นคนรันระบบหละ? คำตอบก็คือ Node ทั้งหลายในระบบนั่นแหละ แต่คนรันระบบจะเปลี่ยนไปเรื่อยๆ โดยระบบจะมีวิธีการคัดเลือกที่เรียกว่า “Concensus algorithm

Consensus algorithm/Protocol/mechanism หรือ ฉันทามติ คือ วิธีการ ที่ทุกคนใน Blockchain Nodes ตกลงและยอมรับร่วมกันเพิ่อให้ได้คุณสมบัติ Byzantine Fault Tolerance (BFT)และ Attack Resistance

1.1) Byzantine Fault Tolerance (BFT)

ต้องมีคุณสมบัติคือ

  • การติดต่อระหว่าง Node จะปลอดภัย
  • บรรลุข้อตกลงร่วมกัน ของ Consensus นั้นๆ ถึงแม้ว่าจะมี Node บางส่วน ที่ผิดพลาด หรือ พยายามโกงระบบ

1.2) Attack Resistance

  • Node ที่ซื่อสัตย์และไม่โกงระบบจะชนะเสมอ
  • การ verify หรือ การยืนยันธุรกกรรม มีต้นทุนที่ต่ำ
  • การ โจมตีระบบ มีต้นทุนที่สูง
  • ไม่ควรทำให้ระบบช้าลง

โดยในโปรเจคนี้ ผมใช้ Proof of Work Consensus

Proof-of-Work คือ ข้อมูลที่ยากที่จะสร้างมันขึ้นมาโดยใครสักคนหนึ่ง แต่ทุกคนพิสูจน์ข้อมูลนั้นๆได้ง่าย

Proof of Work Consensus(PoW) ได้กำหนดไว้ว่า คนแรกที่สามารถสร้างหรือหาข้อมูล (Proof-of-Work) จะได้สิทธิในการยืนยันธุรกรรม และเมื่อบันทึกธุรกรรมสำเร็จ ได้รับรางวัล และ/หรือ ค่าธรรมเนียม เป็นการตอบแทน โดยการพยายามหาคำตอบนี้จะเรียกว่า การขุด(Mine)

Miner เป็นชื่อ เรียก Node ชนิดหนึ่งที่ทำหน้าที่ในการขุด เนื่องจากการขุดทำได้ยาก ส่งผลให้การขุดแต่ละครั้งจะมีต้นทุนคือพลังประมวลผลคอมพิวเตอร์และค่าไฟนั่นเอง

จะเห็นได้ว่า หากไม่มี Miner ระบบจะไม่สามารถดำเนินต่อไปได้ ซึ่งสิ่งสำคัญที่ทำให้ระบบข้างต้นสามารถรันไปได้คือ Miner นั่นเอง สิ่งที่น่าสนใจคือ ระบบนี้จะรันได้ด้วยความโลภล้วนๆ เพราะคนที่จะมาเป็น Miner ล้วนต้องการผลตอบแทนจากการขุดนั่นเอง หากในระบบมี Node จำนวนมาก หรือมีความ Decentralizedเพียงพอ ระบบจะมีความ Fault tolerance หรือ ระบบจะไม่มีทางล่มนั่นเอง

Why Attack Resistance? เบื้องหลังการทำงานของ PoW

หลักของ Proof of Work Consensus ก็คือ

คนแรกที่สามารถแก้สมการทางคณิตศาสตร์จะได้สิทธิในการยืนยันธุรกรรม และเมื่อบันทึกธุรกรรมสำเร็จ ได้รับรางวัล และ/หรือ ค่าธรรมเนียมในการโอนเป็น bitcoin

ซึ่งการที่จะหาคำตอบสมการจากเหล่านี้ทำได้ยากมากกกกกกก โดยจะต้องแก้ด้วยวิธี สุ่มหาคำตอบไปเรื่อยๆด้วยคอมพิวเตอร์เท่านั้น เพื่อพิสูจน์ว่าคนๆนั้นมีการทำงานอย่างหนักเพื่อยืนยันธุรกรรม

แต่ในแง่ของเศรษศาสตร์

ระบบจะต้องเพิ่มต้นทุนของคนกลาง หรือ Miner ในการเปลี่ยนแปลงข้อมูล ให้มากกว่าผลประโยชน์ที่Minerจะได้รับจากการโกงระบบ ทำให้ คนกลางไม่กล้าเสี่ยงที่จะโกงระบบ ด้วยเหตุผลง่ายๆคือ ไม่คุ้ม ไม่ได้กำไร หรือ ขาดทุน นั่นเอง

เมื่อมีคนพยายามจะเปลี่ยนหรือแก้ไขข้อมูลของธุรกกรรมก่อนหน้าในอดีต คนๆนั้นจำเป็นที่จะต้องแก้สมการหาคำตอบใหม่ทั้งหมดตั้งแต่ Block นั้นๆจนถึง Block ปัจจุบัน และยังต้องเพิ่มจำนวน คนในระบบเพื่อยืนยัน คำตอบใหม่ให้มากกว่าครึ่งหนึ่งของระบบด้วย และทั้งหมดนี้ยังต้องทำในเวลาที่จำกัดก่อนที่ Miner คนอื่นจะยืนยันธุรกรรมใหม่ ลงไปใน Block ด้วยทำให้ในทางปฎิบัติ เป็นไปได้ยากมากที่จะเจาะและโกงระบบ Blockchain ที่มีความ Decenctralized สูง เพราะจะเกิดต้นทุนในการประมวลผลที่มหาศาลจนไม่คุ้มทุนนั่นเองครับ

โดย หลักๆ Blockchain จะนำมาใช้แก้ปัญหาความไม่เชื่อถือซึ่งกันและกัน ทำให้คนไม่สามารถโกงระบบได้นั่นเอง และ ระบบจะมีความน่าเชื่อถือ (Trust) มากขึ้น

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

3) (Crypto) Wallet

คือกระเป๋าสตางค์ หรือ สมุดบัญชี นั่นเอง โดยหน้าที่หลักๆก็คือ รับ และ ส่ง value ไปยัง wallet อื่นๆ แต่ crypto wallet จะแตกต่างจาก ระบบบัญชีธนาคารแบบดั้งเดิมคือ

ธนาคารจะเก็บยอดรวมของแต่ละสมุดบัญชีที่แต่ละคนถือ

จะเปลี่ยนมาเป็น

แต่ละบัญชี คือ software ที่เก็บ private key และ public key ซึ่งทั้งสองอย่างนี้เป็นส่วนหนึ่งของการเข้ารหัสแบบ Public Key Cryptography หรือ Asymmetric Cryptography นั่นเอง โดยหลักๆก็คือ สามารถสร้าง Public key จาก Private key ได้แต่ไม่สามารถ ย้อนกลับจาก Private key เป็น Public key ได้นั่นเอง

Pivate Key เปรียบได้กับ password หากเรามี Private key เราจะสามารถส่ง เงินไปให้คนที่เรารู้ Public key ของคนๆนั้นได้

Public key ปรียบได้กับ username หากเราส่ง Public key ไปให้คนอื่นๆ คนที่รู้จะสามารถส่งเงินกลับมาให้เราได้

ซึ่ง Private key จะทำให้เราสามารถ sign รายการเดินบัญชี จากนั้นเก็บ รายการเดินบัญชีลงไปใน Blockchain ซึ่งชื่ออย่างทางการของรายการเดินบัญชีนี้คือ “Transaction ” หรือก็คือการโอนเงินออกนั่นเอง

sign เราสามารถนำ Private key มา sign กับ Transaction ได้เป็น signature ซึ่งบ่งบอกได้ว่า Transaction นั้นถูกส่งมาจากใคร ผ่านการ verify

หรือ sign(private_key, transaction) => signature

verify เราสามารถนำ

Transaction, Signature จาก Transaction นั้นๆ และ Public key จาก Private key ที่ใช้ในการ sign Transaction นั้นๆ มายืนยันว่า Transaction นั้นถูกส่งมาจาก Wallet ที่ถือ public key  นั้นๆ รึเปล่า ส่งผลให้ทุกคนในระบบสามารถยืนยัน Transaction ได้ โดยคนส่งไม่จำเป็นต้องเปิดเผยข้อมูลเกี่ยวกับ Private key ของตนเอง

หรือ verify(public_key, transaction, signature) => true/false

ดังนั้น Private key จะต้องถูกเก็บรักษาไว้เป็นอย่างดี เพราะว่า แค่รู้ Private key สามารถที่จะทำอะไรกับ wallet ก็ได้ ไม่ว่าจะเป็นการสร้าง Wallet มาใหม่ การกู้ (recover) Wallet ที่หายไป รวมไปถึงการสร้าง Transaction เพื่อโอนเงินออกอีกด้วย

จะสังเกตได้ว่าระบบแบบกระจายศูนย์นี้จะไม่มียอดจำนวนรวม มันมีแต่ข้อมูลการเดินบัญชี เช่น

1) Tom ฝากเงินเริ่มต้น 1000 บาท

2) Tom โอนเงินให้ Tim 500 บาท (John เหลือเงิน 500 บาท)

3) Jo-anne โอนเงิน ให้ Tom 200 บาท (Tom มีเงินทั้งหมด 700 บาท)

พออยากรู้ว่าคนๆนั้นมีเงินจำนวนเท่าไหร่ ก็แค่เอารายการทั้งหมดมาบวกลบกัน วิธีนี้เป็นหนึ่งในวิธีที่ แก้ไขปัญหาความเชื่อใจซึ่งกันและกัน เนื่องจากทุกคนสามารถตรวจสอบย้อนกลับไปยังที่มาที่ไปของเงินได้

Transaction Model( UTXO )

เนื่องจาก ระบบแบบกระจายศูนย์ จะมี Miner หลายตัว ที่แข่งกันขุด Transaction, บรรจุลง Block และส่งไปยัง Node อื่นๆ ส่งผลให้เกิด

“Block time” คือ ช่วงเวลาระหว่าง เวลาที่บรรจุ Block หนึ่ง กับ Block ก่อนหน้านั้น

แต่ในความเป็นจริง ธุรกรรมทางการเงินจะเกิดแบบ real-time ทำให้ในขณะที่ เกิด Transaction แต่ยังไม่ได้บรรจุลงใน Block ซึ่งสามารถเรียก Transaction แบบนี้เป็น Unspent transaction output( UTXO )

Transactions Flow in the UTXO Model

จากรูป เห็นได้ว่า Transaction จะ ใช้จ่ายเงินจาก Transaction ก่อนหน้า และจะสร้าง UTXO เพื่อที่จะถูกใช้จ่ายอีกทีโดย Transaction ในอนาคต

Math behind Private and Public keys: เบื้องหลังการทำงานโดย Elliptic Curve Cryptography ( ECC )

Elliptical curves คือ ชุดของจุด {x, y} ของ y^2=x^3+ax+b

กราฟ Elliptical curves ทุกชุดจะมีคุณสมบัติคือ

  • กราฟ จะสมมาตรกับแกน X
  • เส้นตรงใดที่ตัดผ่านจุดใดจุดหนึ่งของกราฟจะตัดผ่านอีกจุดหนึ่งของกราฟเสมอ
  • เส้นตรงใดที่ตัดผ่านจุดสองจุดใดๆของกราฟจะตัดผ่านจุดอีกหนึ่งเสมอ(รวมเป็น 3 จุด)

จากคุณสมบัติข้างต้น ทำให้สามารถ กำหนดคุณสมบัติของจุด (P)ขึ้นมาใหม่ดังนี้:

Point Addiction หรือ คุณสมบัติการบวก: P + Q = R  จุด R คือ จุดที่สมมาตรกับจุดที่สามที่เกิดขึ้นมาเมื่อลากเส้นตรงตัดผ่านจุด P และ Q ตามรูป

จะเห็นได้ว่าการบวกจุดแบบนี้จะแตกต่างจากการบวกจำนวนจริงแบบธรรมดา เช่น 1+1=2 แต่การบวกทั้งสองอย่างล้วนมีสมบัติการบวกเหมือนกันดังนี้

  1. Closure Property:สมบัติปิดให้ a และ b เป็นจำนวนชนิดใดๆแล้ว a+b เป็นชนิดนั้นเช่นกัน
  2. Associativity:สมบัติการเปลี่ยนหมู่ ให้ a,b และ c เป็นจำนวนเต็มใดๆแล้ว (a+b)+c=a+(b+c)
  3. Identity:สมบัติของศูนย์ การบวกจำนวนใดๆ ด้วยศูนย์จะได้ผลบวกเท่ากับจำนวนนั้นๆ
  4. Inverse จำนวนทุกๆตัวจะมีอินเวิร์สของตัวมันเอง a + b =0 (b เป็น อินเวอร์สของ a)
  5. Commutativity:สมบัติการสลับที่ ให้ a และ b เป็นจำนวนเต็มใดๆแล้ว a+b=b+a

Point Doubling เหมือนกับตุณสมบัติการบวกคือ: P+P=2P แต่คราวนี้จะลากเส้น tangent หรือตั้งฉากกับกราฟแทน ดังรูป

การสร้าง Private key และ Public Key สำหรับ Elliptical Curve

การสร้าง Private key และ Public Key สำหรับ Elliptical Curve

  1. สุ่มสร้าง จุด ชื่อว่าจุด G


  2. สมมติว่า ต้องการหา จุด P = k*G ในขณะที่ เรารู้ค่า k เป็น random 256-bit integer (ระหว่าง2^02^256) และ P มีชนิดเป็น จุด (x,y)


    ถ้าหากรู้ ค่า k เราก็แค่ใช้ Point Addition เป็นจำนวน  K ครั้งจนได้ ค่า P= k*G
    แต่ยังมีวิธีที่ลดจำนวนของการบวกได้อีก ยกตัวอย่างเช่น

    สมมติว่า k = 126 และต้องการหา P= 126*G
    กระจายได้เป็น 2^6*G +2^5*G+2^4*G+2^3*G+2^2*G+2*G
    =126*G

    จะเห็นได้ว่าใช้การบวกจุด ไป 5 ครั้ง

    G+G=2G
    2G+2G=4G=2^2G
    4G+4G=8G=2^3G
    8G+8G=16G=2^4G
    16G+16G=32G=2^5G
    32G+32G=2^6G

    และขั้นตอนข้างต้นใช้การบวกจุดไปอีก 6 ครั้ง รวมเป็น 11 ครั้ง
    ซึ่งเร็วกว่าการบวกจุด G ทีละครั้งเป็นจำนวน 126 ครั้ง

  3. สมมติว่า ต้องการหา จุด k = P/G ในขณะที่ เรารู้ค่า P


    คราวนี้เราถูกถามว่า “จะต้องบวกจุด G ไปกี่ครั้งถึงจะได้จุด P ?”
    คราวนี้ไม่สามารถใช้การกระจายเหมือนตัวอย่างที่แล้วจึงต้องบวก G ทีละตัวจนกว่าจะได้ค่า P เห็นได้ว่าการค่า k ใช้เวลานานมากกว่า หาค่า P

อย่างไรก็ตาม ในบางครั้งการบวกจุดอาจจะทำให้ได้จุดที่ห่างไปมากๆหรือเกือบ infinity ทำให้ไม่สามารถคำนวณได้เนื่องด้วยข้อจำกัดของคอมพิวเตอร์ ดังนั้นในศาสตร์ของ crytography เราจะจำกัดช่วงดังนี้

Elliptical Curve Cryptography

โดยเราเปลี่ยนจาก

y^2=x^3+ax+b

เป็น

(y^2)mod p =(x^3+ax+b )mod p ในขณะที่ p เป็นจำนวนเฉพาะ

คราวนี้ช่วงของ จุด (x,y) จะมีค่าระหว่าง 0 ถึง p

เนื่องจาก จุด P สามารถหาได้ง่ายมากๆ และยังแสดงถึง เอกลักษณ์ของค่า k

ส่วน ค่า k หาได้ยากมากๆจนแทบจะเป็นไปไม่ได้เลย ถึงแม้จะรู้ค่า P

จึงสามารถเปรียบเทียบ จุด P ได้กับ username หรือ Public key และ k เป็น password หรือ Private key นั่นเอง

4) Faucet app

โดยทั่วไป คือ เว็บแอพ ที่ถือจำนวนเงินไว้จำนวนหนึ่งโดยโอนมาจาก genesis transaction(จาก Block 0) หรือ คนที่บริจาคให้ faucet

หน้าที่หลักของ Faucet ก็คือจะส่งเงินจำนวนหนึ่งไปยังบัญชีที่คนขอมา หรือ สร้างรายการเดินบัญชี (transaction ) จาก Faucet app ไปยัง Public key ของคนที่ร้องขอเงินมา

Faucet app คือ Wallet อันหนึ่งนั่นเอง

จุดประสงค์หลักก็คือ เอาไว้ทดสอบ Blockchain Network นั่นเอง

5) Explorer app

คือ เว็บแอพ หรือ เครื่องมือที่ใช้ค้นหาและตรวจสอบข้อมูลเกี่ยวกับ Blockchain network

  • ข้อมูลของ Blocks
  • รายการเดินบัญชี ( Transaction )
  • เลขบัญชี( Public key) และ ยอดรวมเงินในบัญชี ( Balance )

Tool Implementation: เลือกใช้เครื่องมือ

Project นี้ตั้งใจว่าจะทำให้เป็นแบบ full-stack ไปเลย คือนอกจาก backend ที่ implement blockchain logic ที่ทำงานได้แล้ว ยังอยากสร้าง UI ให้สวยๆเพื่อติดต่อกับ client ด้วย

เพิ่อความเรียบง่าย โปรเจค ถูก implement โดยใช้ RESTful web API ซึ่งผมจะใช้วิธี Test Driven Development (TDD) เป็นหลัก โดย Framework และ Library หลักๆ ก็มีดังนี้ครับ

Backend

  • Express.js หรือ NodeJs Framework เพื่อทำ RESTful web API
  • Redis ทำ channel เพื่อให้ Node publish และ subscribe หรือก็คือการทำ Synchronisation ระหว่าง Node นั่นเอง
  • Socket.io สำหรับการทำ Real-time feature เพื่อติดต่อกับ Frontend
  • Jest สำหรับ TDD

Frontend

  • Angular 7 Typescript Framework
  • Angular Material เพื่อให้ web app รองรับ mobile responsive

แต่ใน EP นี้ขอเน้นไปที่ Back-end ก่อนครับ

Project Organisation and File Structure: จัดระเบียบโครงสร้างโปรเจค

โปรเจตนี้ใช้ package manager คือ npm โดยผมใช้ Angular-cli command ในการ scaffold Project ซึ่ง Project นี้ใช้ “Sassy CSS” หรือ scss แทนค่า default คือ css

ng new full-stack-blockchain-network --style=scss

ตามหลัก Separation of concerns ผมได้แยก frontend กับ backend ออกจากกัน

cd full-stack-blockchain-network/
mkdir backend
File Structure

Separation of concerns คือ Design Principle แบบหนึ่งที่แบ่งโค้ดออกเป็นส่วนๆ เป็นไฟลล์หลายๆไฟลล์ ต่างคนต่างมีหน้าที่การทำงานของตัวเอง ไม่จับมารวมกัน เป็นโค้ดยาวๆ ทั้งนี้เพื่อให้โค้ดของเราอ่านและดูแลง่ายขึ้น

Let Code!

1) Designing Blockchain Network: RESTful API Requirement

ผู้ใช้บัญชีสามารถติดต่อได้กับ แอพ ผ่านสามส่วนดังนี้ คือ wallet, explorer และ faucet app นั่นเอง

  • GET:http://{host}:port/
  • GET:http://{host}:port/wallet-info
  • POST:http://{host}:port/wallet/recover
  • POST:http://{host}:port/wallet/create
  • POST:http://{host}:port/wallet/transact
  • GET:http://{host}:wallet/mine-transactions/
  • GET:http://{host}:port/wallet/start-mining-transactions
  • GET:http://{host}:port/wallet/stop-mining
  • GET:http://{host}:port/explorer/blocks
  • GET:http://{host}:port/explorer/blocks/:blockId
  • GET:http://{host}:port/explorer/transactions
  • GET:http://{host}:port/explorer/transaction-pool-map
  • GET:http://{host}:port/accounts
  • GET:http://{host}:port/faucet/request

จากรูป ได้แบ่ง ฟีเจอร์หลักๆทั้งหมด ของ Blockchain service ออกเป็น สามส่วนคือ explorer, faucet และ wallet จากนั้นสร้างไฟลล์เพื่อแบ่ง route หรือ url ออกเป็นโมลดูล

จากนั้น ตามหลัก ของ MVC patten ผมได้สร้างโฟลเดอร์ตามรูปด้านบน

MVC Pattern

Model คือส่วนที่เก็บข้อมูลของ แอพ เรา ในที่นี้คือ Blockchain นั่นเอง

View คือ ส่วนที่ไว้แสดงผลข้อมูลให้กับ User และยังทำหน้าที่ติดต่อกับ User แต่ในที่นี้ได้ถูกจัดให้ในส่วนของ Frontend หรือ Angular นั่นเอง

Controllers คือส่วนที่เอาไว้ใช้จัดการกับ Model โดยจะขึ้นอยู่กับการกระทำที่เกิดมาจาก View และยังทำหน้าที่หาข้อมูลจาก Model เพื่อนำไปแสดงผลที่ View ด้วย

และสามารถเขียน RESTful Web app โดยใช้ express ดังนี้

backend/index.js

2) Building the Blockchain Node Requirement

คอย sync กับ Node อื่นๆ เพื่อเก็บและอัพเดตข้อมูลต่างๆเป็นชุดเดียวกัน คือ

  • Block Data หลายๆ Block มาต่อรวมกันเป็น Blockchain
  • Unconfirmed Transaction (หรือ Transaction Pool)
backend/index.js

ในการรัน Node อันแรก จะใช้คำสั่ง:

npm run dev

เมื่อต้องการรัน Node อันต่อๆไป เพื่อ Synchronise กับ Node อันแรกจะใช้คำสั่ง:

npm run dev-peer

ซึ่งสามารถรันคำสั่งอื่นๆ ใน Terminal Command ได้ดังนี้

package.json

Synchronisation

ผมเขียน class pubsub เพื่อใช้ในการสร้าง Channel และ method ในการ publish , subscribe รวมไปถึง broadcast

pubsub.js

Block and Blockchain Data Structure

Block

Data เป็น Property ที่เก็บ array ของ Transaction data structure
SHA256 คือ hash function ชนิดหนึ่ง

block.js

Nonce เป็นค่าที่ถูกวางไว้ใน Block เพื่อให้เราวนหาค่าไปเรื่อย ๆ จนกว่า Block นั้นจะ mine หรือหาคำตอบทางคณิตศาสตร์ ซึ่งก็คือ Proof-of-Work ได้นั่นเอง

โดยเงื่อนไขก็คือ
SHA256 (ข้อมูลทั้งหมดใน Block)ที่นำหน้าด้วย 0 จำนวนหนึ่ง ซึ่งจะเป็น 0 กี่ตัวขึ้นอยู่กับค่า difficulty ในตอนนั้น หากค่า difficulty มาก ยิ่งหาคำตอบยาก เช่น ต้องการเลข 0 นำหน้า 2 ตัว ก็ต้องเปลี่ยนค่าไปเรื่อยๆ จนได้ค่าที่ต้องการเช่น


005603f7bfb22139228fa5149495661ac70fcf10cd6cf31bbbe007cf16e945bb

ยิ่งมี 0 นำหน้ามากเท่าไหร่ ยิ่งหาคำตอบได้ยากมากเท่านั้น

โดย สามารถ implement logic ของ การ mine ได้ตามรูป

block.js
blockchain.js

ในกรณีที่ Node มีการขุดแข่งกัน Node ที่สามารถหาคำตอบได้ก่อนจะทำการ Broadcast chain ของ Node จากนั้น Peer Node ที่กำลัง subscribe อยู่ จะใช้ method replaceChain เพื่อ sync chain กับ Node

blockchain.js

3) Wallet Requirement

  • สร้าง และ เก็บ Private key
  • Recover Wallet ที่หายด้วย Private key
  • คำนวณ Balance
  • สร้าง Transaction
  • Sign Transaction

โดยใน ไฟลล์โมดูลของ Wallet ได้แบ่งเป็นดังนี้:

wallet/index.js

ตามที่ได้กล่าวไปแล้ว ในส่วนของ Key ต่างๆ จะใช้หลักของ Elliptic Curve Cryptography ซึ่งใน javascipt เรามี library สำหรับด้านนี้โดยเฉพาะ ตามลิ้งครับ https://github.com/indutny/elliptic  โดยสามารถนำไปใช้ได้ดังนี้

wallet/index.js

transaction.js

โดยหลักๆ Transaction จะประกอบไปด้วย

  • id ซึ่งแต่ละอันจะไม่ซ้ำกัน โดยใช้ library ชื่อว่า uuid
  • outputMap เมื่อนำมา map กับ publickey ของผู้รับ จะได้จำนวนเงินที่ส่งไป
  • input ประกอบไปด้วย timestamp, จำนวนที่สามารถส่งได้, publickey ของผู้ส่ง และ ลายเซ็น ของ transaction นั้นๆ
transaction.js

นอกจาก logic ของ Transaction ที่ได้กล่าวข้างต้น method update  ซึ่งจะรวม Transaction หลายอัน ที่มี publicKey ของ input ตรงกัน เป็นอันเดียวกัน หรือพูดอีกอย่างก็คือ ทำให้ Transaction สามารถประกอบไปด้วย outputMap หลายๆอันนั่นเอง

transaction.js

transaction-pool.js

ซึ่งก็คือ Unspent transaction output( UTXO ) นั่นเอง

transaction-pool.js

4) Miner Requirement

หรือก็คือ Wallet ที่เพิ่มความสามารถเข้ามาคือ

  • mine Transaction pool
  • จากนั้น บันทึกเป็น confirmed transaction ลงใน Block แล้วต่อกับ Block ก่อนๆ เป็น Blockchain
transaction-miner.js

method startMing จะทำหน้าที่ mineTransaction ต่อไปเรื่อยๆ เป็นลูปแบบไม่มีที่สิ้นสุด ก่อให้เกิดการแข่งขันการขุดระหว่าง Node ต่างๆ

transaction-miner.js

4) Faucet app Requirement

  • สร้าง Transaction ให้กับ Wallet ที่ request มา
  • มีจำนวนเงินอยู่ใน Faucet wallet เป็นจำนวนมาก

โดยผมได้ hardcode ว่า มี Transaction ไปยัง public key ของ Faucet wallet

model/config.js

เมื่อมีคนต้องการจะ request เงินจาก faucet ตัว Faucet app จะถูก recover เพื่อนำมาส่ง ด้วย Private Key ตามภาพ

network/index.js

5) Explorer App Requirement

  • ดู Transaction ที่ถูกยืนยันไปแล้ว
  • ดู mined Block
  • ตรวจสอบ บัญชี( address) และ จำนวนเงิน

ซึ่ง เราจะเรียกข้อมูลของ Model เหล่านี้ผ่านทาง Controller ด้วย GET method ดังนี้ครับ

routes/explorer.js

ขั้นตอนต่อไปก็คือ สร้างส่วน frontend มาแสดงผลของข้อมูลครับ

Conclusion and my Thought: สรุป

การ พัฒนาในส่วน ของ backend สิ่งที่สำคัญที่สุดสำหรับผมก็คือ การเข้าใจใน business logic ซึ่งไม่จำเป็นว่าต้องเป็น blockchain แต่ยังรวมไปถึงเรื่องใดๆก็ได้ในโลกนี้ จากนั้น โค้ดความเข้าใจเหล่านั้นเขียนออกมาเป็นโค้ด

ผมเชื่อว่า code ที่ดีคือ code ที่ทุกคนอ่านและเข้าใจมันได้ง่ายครับ

คิดว่า คงพอจะเห็นภาพคร่าวๆ ในส่วนของหลังบ้านแล้ว ใน EP ต่อไปจะขอพูดถึง การ Architect Angular เพื่อสร้าง Frontend ตามลิ้งครับ https://geekactuary.com/full-stack-blockchain-test-network-with-angular-nodejs-ep2-front-end-architecture-with-angular/

Related posts