ตัวอย่างระบบ Vote ด้วย Smart Contract บน Ethereum Blockchain

บทความนี้นำเสนอตัวอย่างการสร้างระบบการลงคะแนนอย่างง่าย (Simple Voting) ด้วย Smart Contract บน Ethereum Blockchain โดยเริ่มตั้งแต่ขั้นตอนการอธิบายภาพรวม ติดตั้งส่วนเสริม เขียน Smart Contract ตลอดจน Deploy ไปที่ Blockchain เพื่อไม่ให้เสียเวลาเริ่มกันเลยดีกว่าครับ

ภาพรวมระบบการลงคะแนน

เพื่อให้ง่ายต่อความเข้าใจ ผมขอยกตัวอย่างสมมติเหตุการณ์ว่าในป่าแห่งหนึ่งจะมีการเลือกเจ้าป่าประจำปีซึ่งปกติจะจัดกันเป็นประจำทุกปี แต่ปีนี้พิเศษสุดๆตรงที่จะมีการใช้ระบบการลงคะแนนเลือกเจ้าป่าผ่าน Smart Contract บน Blockchain (ป่าแห่งนี้ไฮเทคมากๆ) โดยมีเงื่อนไขการลงคะแนนดังต่อไปนี้

1. เจ้าป่าคนก่อน คือ สิงโต จะเป็นคนกำหนดว่าที่เจ้าป่าคนใหม่ (candidate) ของปีนี้

2. เมื่อกำหนด candidate แล้ว สิงโต จะเป็นคนประกาศให้เริ่มและสิ้นสุดการลงการลงคะแนนได้เพียงผู้เดียวเท่านั้น

3. เมื่อสิงโตประกาศให้เริ่มการลงคะแนนแล้ว ผู้ลงคะแนน (voter) จะสามารถลงทะเบียนให้กับ candidate ได้ 1 ครั้ง / 1คน เท่านั้น

4. สุดท้าย ทุกคนจะสามารถดูผลการลงคะแนนของแต่ล่ะ candidate ได้ ก็ต่อเมื่อสิงโตประกาศให้สิ้นสุดการลงคะแนนแล้วเท่านั้น

ต่อมาเรามาสร้างระบบตามเงื่อนไขข้างต้นกันครับ

ติดตั้ง Metamask

เริ่มจากติดตั้ง Metamask เป็นกระเป๋า (wallet) สำหรับบริหารจัดการ Ethereum และ Token บน Ethererum Blockchain โดยสามารถติดตั้งได้ที่ metamask.io ขั้นตอนนี้ผมขออนุญาตไปนะครับ

เมื่อได้ account แล้ว ขั้นตอน ต่อมาเราจะขอ ETH เข้า wallet ของเรา

ในตัวอย่างนี้ ผมจะใช้เป็น Ropsten Test Network ดังรูปต่อไปนี้

จากนั้นให้เข้าไปที่ https://faucet.metamask.io/ และกดที่ request 1 ether from faucet ดังรูป

จะพบว่าเราจะได้ ETH เข้ามาใน wallet

ออกแบบ Smart Contract

เพื่อให้ได้เงื่อนไขตามระบบลงคะแนนที่กำหนด ผมได้สรุปตัวแปร (Variable) และ ฟังก์ชั่น (Function) ของ Voting Contract โดยมีรายละเอียดสรุป ดังรูปต่อไปนี้

เขียน Smart Contract

ผมใช้เครื่องมือในการเขียน คือ Remix ซึ่งเป็น IDE ที่สามารถเขียน compile และ deploy และภาษาที่ใช้ คือ Solidity

โดยให้เข้าไปที่ https://remix.ethereum.org > เลือก Solidity > เลือก New file > ตั้งชื่อไฟล์ SimpleVoting.sol

จากนั้นใส่ code ดังต่อไปนี้

จากนั้น compile โดยไปที่หน้า SOLIDITY COMPILE > เลือก 0.7.6+commit > กด Compile SimpleVoting.sol ดังรูป

Deploy และ การใช้งาน

จากนั้น Deploy ไปที่ Blockchain โดยผู้จัดการลงคะแนน (Manager) จะเป็นผู้กำหนด candidate ซึ่งในตัวอย่างนี้ คือ cat dog และ birdโดยมีขั้นตอนดังต่อไปนี้

1. DEPLOY & RUN TRANSACTIONS

2. เลือก environment เป็น Injected Web3

3. ใส่เป็น ["cat", "dog", "bird"]

4. กด Deploy

จากนั้น กด Confirm ค่า Gas ดังนี้

เมื่อ deploy เรียบร้อยแล้ว จะพบ Deployed Contracts ซึ่งจะพบฟังก์ชั่นต่างๆที่เราสามารถเรียกใช้งานได้

เพื่อให้เข้าใจขั้นตอนการทำงานข้างต้นมากยิ่งขึ้น ผมจึงสร้างภาพออกมาเพื่อแสดงค่าตัวแปรต่างๆ ดังรูปต่อๆไป

โดย สิงโต จะเป็นคน deploy Voting Contract พร้อมกับกำหนด candidate คือ cat, dog และ bird จากนั้น state จะเปลี่ยนเป็น 0 หรือ Created

ต่อมาเริ่มให้ลงคะแนน โดยเรียกฟังก์ชั่น startVote() โดยขั้นตอนนี้ สามารถเรียกได้เฉพาะคนที่ deploy smart contract เท่านั้น ดังนี้

จะพบ สิงโต จะไปเรียก startVote() จากนั้น state จะเปลี่ยนเป็น 0 หรือ Voting

จากนั้นจะเข้าสู่ขั้นตอนการลงคะแนน โดยใครก็ได้ที่มี account สามารถลงคะแนนได้ โดย 1 ครั้ง / 1 account เท่านั้น ตัวอย่างเช่น ต้องการลงคะแนนให้ cat โดยใช้ฟังก์ชั่น voteForCandidate โดยกรอก “cat” > กด voteForCandidate ดังนี้

จากขั้นตอนข้างต้น สมมุติว่า bird ลงคะแนนให้ cat จะสังเกตุว่า votesReceived ที่อยู่ตำแหน่ง (index) เดียวกันกับ cat จะเพิ่มขึ้น 1 และ isVoted จะจัดเก็บ address ของ bird เพื่อแสดงว่า bird ได้ลงคะแนนไปแล้ว

***ในรูปนี้ผมทำให้เข้าใจง่ายขึ้น แต่การทำงานจริง จะเป็นการ + 1 โดยใช้ “cat” เป็น index ดังนี้ votesReceived[“cat”] += 1

ลองเปลี่ยน account และทดลองลงคะแนนให้ cat อีกครั้ง (บน Remix)

*** เพิ่ม account ใหม่ โดยไปที่ Metamask > กดที่ icon ขวาบน > กด Create Account > ให้ขอ ETH ตามขั้นตอนเดิม

เมื่ออธิบายเป็นรูปก็จะเห็นว่า cat ลงคะแนนให้ cat ก็จะพบว่าคะแนนของ cat เพิ่มขึ้นอีก 1 และ isVoted จะจัดเก็บ address ของ cat เพิ่ม ดังรูป

ลองเปลี่ยน account อีกครั้ง และลงคะแนนให้ dog บ้าง ดังนี้

เมื่ออธิบายเป็นรูปจะเห็นว่า fish ลงคะแนนให้ dog ก็จะพบว่าคะแนนของ dog เพิ่มขึ้น 1 และ isVoted จะจัดเก็บ address ของ fish เพิ่ม ดังรูป

ต่อมาเมื่อถึงเวลาปิดการลงคะแนน Manager จะมาเรียกฟังก์ชั่น endVote() โดย เฉพาะ Manager เท่านั้น ถึงจะสั่งคำสั่งนี้ได้ ดังนี้

ดังนั้น เมื่อ สิงโต สั่งคำสั่ง endVote() จะพบว่า state จะกลายเป็น 2 หรือ Ended

ตอนนี้ ทุกคนก็จะสามารถเรียกดูผลการลงคะแนนได้โดยใช้คำสั่ง totalVotesFor() โดยระบุ candidate ที่ต้องการได้ เช่น ผลการลงคะแนนของ cat คือ 2 ดังต่อไปนี้

อธิบายโดยรูปจะเห็นว่าตอนนี้ทุกคนก็สามารถเรียกดูผลคะแนนของแต่ละ candidate ได้เลย

เท่านี้เราก็สามารถสร้างระบบลงคะแนนด้วย Smart Contract บน Blockchain ได้เรียบร้อยแล้ว

อย่างไรก็ตามในบทความนี้ยังไม่ได้ลงรายละเอียดของ Smart Contract ขออนุญาตอธิบายในบทความต่อๆไปถ้ามีโอกาสนะครับ สุดท้ายนี้หวังว่าบทความนี้คงไม่ประโยชน์ไม่มากก็น้อยนะครับ ขอบคุณมากๆครับ

บทความโดย อ.ผศ.ดร.ธรรณพ อารีพรรค

วิทยาลัยนวัตกรรมดิจิทัลเทคโนโลยี มหาวิทยาลัยรังสิต