ZMINE BLOG

English English   ไทย ไทย

How ZMINE generate random numbers from Smart Contract (2)

Share this article

จากที่ได้กล่าวมาแล้วใน บทความส่วนแรก ถึงวิธีการ Random แบบต่างๆ ในบทความนี้เราจะมาพูดถึงการ Random ที่ ZMINE ใช้แจกรางวัล ST Rewards กันครับ

การออกแบบ

โจทย์ของการ Random ก็คือต้องสามารถ Random ค่าระหว่างเลข 1 ถึง n ได้ โดย n คือจำนวนสิทธิที่ของ ST Rewards ในรอบนั้นๆ สำหรับคุณสมบัติต่างๆที่ต้องการมีดังนี้

  1. โปร่งใส ตรวจสอบย้อนหลังได้ ซึ่งคุณสมบัติข้อนี้เป็นพื้นฐานของเทคโนโลยี Blockchain ดังนั้นการเลือกเอา Smart Contract ใน Ethereum Network มาใช้จึงสามารถตอบโจทย์ได้เป็นอย่างดี
  2. คาดเดาผลลัพธ์ได้ยาก หรือหา Seed ที่ไม่สามารถคาดเดาได้โดยง่ายนั่นเอง ซึ่งในส่วนนี้เราได้ออกแบบให้ใช้ทั้งการสร้าง Seed แบบ True Random Number Generator และส่วนที่เป็นการสร้าง Seed แบบ Pseudo Random Number Generator ผสมกัน
  3. ง่ายและรวดเร็ว วิธีการที่ใช้ควรไม่ซับซ้อน สามารถให้ผลลัพธ์ได้ทันที ดังนั้นเราจึงตัดการใช้วิธี Random แบบใช้ Third party API ออก (เช่น random.org) หรือการ Random แบบที่มีความซับซ้อนสูงและใช้เวลานาน เช่น  RANDAO  ออกไป
  4. จำนวนและช่วงเวลาที่ใช้ข้อมูล การ Random ทำเดือนละ 2 ครั้ง ทุกวันที่ 1 กับ 16 จำนวนเลขประมาณ 10-20 จำนวนต่อครั้ง

จากที่กล่าวมาข้างต้นทางทีมงานได้ออกแบบที่มาของ Seed ได้ดังนี้

  1. Counter (Nonce) คือตัวแปรจำนวนครั้งที่ Random เลขนี้จะเพิ่มขึ้นทีละหนึ่งทุกคร้ังที่การ Random สำเร็จ
  2. Variables in Ethereum Network ได้แก่ ตัวแปร Block No (เลข Block ก่อนหน้า) และ Block Difficulty ซึ่งมีการเปลี่ยนแปลงในทุกๆ Block ที่เกิดขึ้น ทั้งสองตัวแปรนี้ถือว่าเป็นตัวแปรที่นำมาใช้ได้ง่าย เวลาเขียน Smart Contract เราสามารถเรียกค่าตัวแปรเหล่านี้ออกมาใช้ได้เลย อย่างไรก็ตามตัวแปรเหล่านี้เป็นตัวแปรที่สามารถคาดเดาได้ง่าย
  3. Third-party Random ทางทีมงานเลือกใช้ ผลฉลากกินแบ่งรัฐบาลมาใช้ เนื่องจากเป็นการสุ่มที่มีความน่าเชื่อถือ และช่วงเวลาสอดคล้องกับที่ ST Rewards ต้องใช้คือวันที่ 1 และ 16 ของเดือน

เมื่อได้แหล่งสร้าง Seed ทั้ง 3 แหล่งแล้ว ก็จะนำมาใช้ในการสร้างเลขสุ่มผ่านการ Hash (Algorithm KECCAK-256)  ที่จะทำให้ได้ผลลัพธ์เป็นเลข uint256 ซึ่งการ Hash นี้จะให้ผลลัพธ์ออกมาค่อนข้างมีการกระจาย กล่าวคือถึงแม้ตัวเลข Seed จะเปลี่ยนไปแค่หลักเดียว แต่ผลลัพธ์การ Hash ก็จะออกมาแตกต่างจากเดิมมาก

หลังได้ผลลัพธ์การ Hash แล้ว เราก็จะนำมาทำให้อยู่ในช่วงตัวเลขที่เราต้องการ (1 ถึง n) ด้วยการ Modulo (%)

Smart Contract

ทางทีมงานได้เขียน Smart Contract ชื่อ ZmineRandom เพื่อใช้ในการ Random ST Rewards สามารถตรวจสอบได้จาก URL https://etherscan.io/address/0xF912eFb4E59Cd2910D90a78b1c1491a870c54b12 ซึ่งมีการ Verified Source Code ไว้เรียบร้อยแล้ว

ZmineRandom จะทำการ Random ค่า โดยเฉพาะผู้ที่มีสิทธิเท่านั้นถึงจะทำการ Random ได้ (Authorizors) เมื่อทำการ Random แล้วจะทำการเก็บค่า Seed ที่ใช้ไว้ด้วย เพื่อให้สามารถตรวจสอบย้อนหลังได้

ข้อมูล Smart Contract: ZmineRandom บน Etherscan

จาก Code จะเห็นว่าในการ Random จะกำหนดตัวแปร 3 ตัวได้แก่

  1. min : ค่าที่ Random ได้ (จำนวนเต็ม) ตํ่าสุดที่เป็นไปได้
  2. max : ค่าที่ Random ได้ (จำนวนเต็ม) สูงสุดที่เป็นไปได้
  3. lotto: ตัวเลข Random จากภายนอก (ผลฉลากกินแบ่งรัฐบาล ไล่ไปตั้งแต่รางวัลที่ 1,2,3 ตามลำดับ)

เมื่อทำการ Random ได้แล้วก็จะเก็บผลลัพธ์ไว้ที่ randomResultMap และเก็บ Seed ไว้ใน randomInputMap ซึ่งสามารถตรวจสอบได้จากแทป Read Contract ใน Etherscan

Note: จาก Source Code ข้างต้น จะสังเกตได้ว่า Seed แต่ละตัวเมื่อผ่านการ Hash แล้วจะนำมา “+” กัน ซึ่งตรงนี้ต้องระวังเพราะอาจเกิดการ Overflow ของตัวเลขได้ เนื่องจาก uint256 จะมีค่าสูงสุดคือ 2**256-1 หรือประมาณ 1.157920892373162e+77  อาจดูเป็นตัวเลขที่เยอะมาก แต่ผลลัพธ์การ Hash ก็มักให้ตัวเลขที่มากเหมือนกัน ยกตัวอย่างเช่น

uint256(keccak256(abi.encodePacked(1))) = 8.008442285988055e+76
uint256(keccak256(abi.encodePacked(2))) = 2.910267648167304e+76

uint256(keccak256(abi.encodePacked(3))) = 8.790302987107592e+76

จะเห็นได้ว่าแค่ 3 พจน์นี้รวมกันก็ Overflow แล้ว ดังนั้นการ + – x %  ใน Smart Contract นั้นควรที่จะใช้ Library SafeMath เสมอ เพื่อป้องกันการ Overflow หรือ Arithmetic error เช่นการหารด้วย 0 เป็นต้น

อย่างไรก็ตาม เนื่องจาก Smart Contract นี้มีจุดประสงค์คือการ “Random” ดังนั้นจึงไม่สนใจว่าจะเกิดการ Overflow หรือไม่ กล่าวคือถ้า Overflow ก็เหมือนการเอาฉลากจากโถเก่ามาใส่โถใหม่เท่านั้นเอง ยิ่งมั่วยิ่งดี 🙂

ตัวอย่างการอ่านค่าจาก Smart Contract ผ่านทาง Etherscan

การ Random ST Rewards ครั้งที่ 1 จำนวน 9 รางวัลได้ผลลัพธ์ดังนี้

Counter TxID Min Max ThirdParty Random No. Random Result
#1 0x73722ce3ada144c1845e97b7ff9a6106c65b44aba5e5687b5d6bcc689ffd197b 1 320,261 452643 037425
#2 0x58ba0a9731e1fae4e5c1fe7fc93131db4fce617163ce58ebcb9aa8216a31df90 1 320,261 261071 293284
#3 0x680e2ce365568085f3716834f61d4e7f51b0495ee4709d5caee9f47d9466adf3 1 320,261 350893 055588
#4 0x656862b0cccb8dd3ba405672868f11c706463dac9bacd488e69f8f76a209e639 1 320,261 616843 267931
#5 0x5be1ee99be7ac4f67950eab68f6c34f9badf950b61fe982068a5411b7feadd8c 1 320,261 875042 056760
#6 0x76affdae124a196cdfc3b784a2916591d3097adf7ed954abcca68b6a7e3e1606 1 320,261 964263 076413
#7 0x7ec93b92772d745ad2db965ee3e5cfb52a6099d40f78c14e5faee5f7b5183bf3 1 320,261 021460 078133
#8 0x69fa2cc01ae5f08b66c608be70e854d27e084a687eb5a75e6604f3ec7a69cc8f 1 320,261 315781 289283
#9 0x1cc67b412c42097b5bbb1c351280d076dfa67861107c7f4f1516a9c4905feba9 1 320,261 239381 275876

จากแทป Read Contract ใน Etherscan

ข้อ 2. counter เป็นการบอกว่ามีการ Random ไปแล้ว 9 ครั้ง

 

 

 

 

ข้อ 4. randomResultMap เป็นการบอกผลลัพธ์การ Random จากรูป การ Random ครั้งแรกให้ผลลัพธ์ 37425

 

 

 

 

 

 

 

 

ข้อ 6. randomInputMap เป็นการเก็บ Seed ทั้งหมดที่ใช้ในการ Random ประกอบด้วย

  • Index 0: Min
  • Index 1: Max
  • Index 2: Lotto
  • Index 3: Block Difficulty
  • Index 4: Block No

 

สำหรับเลขที่ใช้ Lotto สามารถตรวจสอบได้จากผลสลากกินแบ่งรัฐบาลไทยล่าสุด เช่น ST Rewards ครั้งที่ 1 ตรงกับผลสลากงวด 1 October 2018 ตามลำดับ รางวัลที่ 1, 2, 3 …

Note: Random #8 ใช้ 315781 และ Random #9 ใช้ 239381 สลับลำดับกัน เนื่องจากความผิดพลาดเล็กน้อย 😛

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

สรุป

ST Rewards เป็นการแจกรางวัลแบบสุ่ม ซึ่งทางทีมงาน ZMINE ได้ให้ความสำคัญกับเรื่องของความโปร่งใส และต้องการให้ทุกคนสามารถเข้ามาร่วมกันตรวจสอบได้ จึงได้นำหลักการของ Smart Contract มาทำการ Random และเก็บข้อมูลย้อนหลังไว้ หวังว่าบทความนี้จะเป็นประโยชน์ต่อทุกท่านนะครับ 🙂