"Fly high but don't fly alone"
Blockchain for Geek ... เบื้องหลังการทำงานฉบับ Technical ตัวอย่างจาก Bitcoin
26 Dec 2016 05:35   [31523 views]

บล็อกต่อเนื่องจากบล็อกเก่า "Blockchain คืออะไร? อธิบายแบบละเอียด แต่เข้าใจง่าย(มั้ง)" ใครยังไม่ได้อ่านอันเก่าอยากให้อ่านก่อนเน้อ เพราะเนื้อหามันต่อเนื่องกัน

บล็อกเก่าเราปูพื้นฐานให้เห็นภาพรวมทั้งหมดก่อนโดยใช้ภาษามนุษย์ แทบไม่ได้พูดถึงเรื่องคอมพิวเตอร์เลย เพราะว่า Target Audience ของบล็อกที่แล้วคือคนทั่วไป หลาย ๆ อย่างก็เลยลงรายละเอียดไม่ได้

แต่บล็อกนี้เราจะลงลึกไปอีกขั้นโดยจะพาไปดูด้าน Technical จริง ๆ จัง ๆ กันละว่าแต่ละอย่างที่พูดในบล็อกเก่าเนี่ยมันคืออะไรในทางคอมพิวเตอร์ ดังนั้น ... บล็อกนี้ Geek นะครับ จะพ่นภาษา Technical เต็มที่ จึงไม่เหมาะแก่คนที่ไม่มีพื้นฐานด้าน Technical บล็อกที่แล้วเป็นการ Design ส่วนบล็อกนี้คือ Implementation

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

อย่างที่บอกไว้ตั้งแต่บล็อกที่แล้วว่า Blockchain มันก็เป็นแค่กลไกที่สามารถต่อยอดไปทำอะไรได้หลายอย่างอ่ะเนอะ ดังนั้นถ้าจะให้อธิบายครบทั้งระบบได้ก็ต้องเอากรณีตัวอย่างที่ต่อยอดแล้วมาอธิบายให้ฟัง เพื่อที่พอศึกษาจนเข้าใจแล้วจะได้สามารถต่อยอดไปทำระบบของตัวเองได้

ซึ่งก็นะ ... ถ้าพูดถึง Blockchain แล้วก็คงไม่มีเคสไหนที่ดีไปกว่า Bitcoin อีกแล้วหละ ดังนั้นบล็อกนี้เลยจะขอยกเอาระบบของ Bitcoin มาอธิบายเป็นตัวอย่างคร้าบผม

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

เรารู้อะไรแล้วบ้างเกี่ยวกับ Blockchain

นี่คือหน้าตาของ Blockchain จากบล็อกที่แล้ว

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

และด้วยกลไกที่อธิบายไปทั้งหมด เช่น Proof of Work ก็จะทำให้ฐานข้อมูลนี้ไว้ใจได้และปลอมแปลงยากมากจนถึงขั้นทำไม่ได้เลย ส่วนสมุดบัญชีที่ทุกคนถือไว้ก็เอาไว้แสดงความเป็นเจ้าของในข้อมูลที่อยู่ใน Blockchain อีกทีนึง

แล้วสิ่งที่ยังไม่รู้หละมีอะไรบ้าง ? ... แนวทางอ่ะได้ละ แต่ที่ยังไม่รู้คือ Implementation ทางคอมพิวเตอร์

1) สมุดบัญชีแท้จริงแล้วคืออะไรในโลกดิจิตอล ?

2) รูปหน้ากล่องในแต่ละ Block จริงๆแล้วคืออะไร?

3) การว่ายน้ำงมเข็ม (Proof-of-Work) จริงๆคือการทำอะไรกันแน่?

และเราจะได้คำตอบพวกนี้กันในบล็อกนี้ครับ

พื้นฐานที่ต้องรู้ก่อนจะไปต่อ

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

- Public Key Crytography (Asymmetric Cryptography)

- Hash Function

ก็แค่นี้แหละ ไม่มีอะไรมากหรอก สำหรับคนที่มาสายคอมพ์เรื่องพวกนี้เราถือว่าเป็นพื้นฐานที่ทุกคนควรรู้นะ แต่ถ้าใครยังไม่รู้ลองไปศึกษาก่อนได้ครับ

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

สมุดบัญชีแท้จริงแล้วคือ Public/Private Key

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

ถามว่าในเชิงคอมพิวเตอร์แล้วข้อมูลสองอย่างนี้คืออะไรในโลกดิจิตอล ? คำตอบคือ

1) ลายเซ็น (Owner Key) คือ Private Key

2) เลขที่บัญชี (Address) คือ Public Key (ที่ถูกย่อส่วนแล้ว)

สำหรับคนที่เห็นคำว่า Public Key และ Private Key น่าจะร้องอ๋อกันละ มันคืออะไรครับ ? ถูกต้องงง มันคือส่วนหนึ่งของการเข้ารหัสแบบ Public Key Cryptography หรืออีกชื่อหนึ่งคือ Asymmetric Cryptography นั่นเองงงง

นี่คือขั้นตอนที่เกิดขึ้นตอนที่สมุดบัญชีเล่มใด ๆ ถูกสร้างขึ้น

ขั้นตอนที่ 1: แรกเริ่ม Private Key จะถูกสร้างขึ้นมาก่อนเป็นตัวเลขขนาด 256 บิต [32 bytes] (จะมีบ้างบางเจ้าที่สร้างเป็นตัวเลข 512 บิต [64 bytes]) โดยใช้กลวิธีที่แต่ละเลขที่ถูกสร้างขึ้นมามีโอกาสซ้ำกันน้อยมากจนอนุมานได้ว่าไม่มีโอกาสซ้ำกันได้เลยก็ได้ และรหัสนี้ถือเป็นรหัสลับที่เอาไว้แทนความเป็นเจ้าของสมุดบัญชีเล่มนี้ครับ ห้ามหลุดหรือห้ามให้คนอื่นเป็นอันขาด และที่สำคัญ ห้ามหายยยย

ขั้นตอนที่ 2: ต่อมา Public Key จะถูกสร้างขึ้นจาก Private Key (สำหรับคนที่ทราบเรื่อง Public Key Cryptography ก็คงจะรู้อยู่แล้วว่า Public Key นั้นถูกสร้างขึ้นจาก Private Key อีกที) โดยใช้กลวิธีที่ชื่อว่า Elliptic Curve Digital Signature Algorithm (ECDSA) ซึ่งจะทำให้ได้ Public Key ที่สะท้อนตัวตนของ Private Key ได้ นั่นแปลว่ามันจะไม่มีโอกาสซ้ำกัน (เพราะ Private Key ไม่ซ้ำกัน) โดย Public Key จะมีขนาดความยาวที่ 65 bytes ครับ

สำหรับ Public Key นี้เป็นข้อมูลสาธารณะ สามารถแชร์ให้ทุกคนได้ เพราะถึง Public Key จะถูกสร้างจาก Private Key แต่มันไม่สามารถทำกลับให้เป็น Private Key ได้ เลยปลอดภัยที่จะแชร์ไปสู่สาธารณะครับ

แต่ Public Key นั้นยาวมากกกกก ในโลกของ Bitcoin ก็เลยไม่ใช้ Public Key ตรง ๆ แต่จะเอา "Public Key ที่ถูกย่อส่วนแล้ว" มาใช้งานจริงแทน

ขั้นตอนที่ 3: Hash Public Key จนกลายเป็นชุดตัวอักษร Base58 ขนาดความยาว 33-34 ไบต์ เช่น 1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz และเราจะเรียก Public Key Hash นี้ว่า Bitcoin Address ครับ และนี่แหละคือ เลขที่บัญชี ของสมุดบัญชีเล่มนี้ครับ สามารถแชร์สู่สาธาณะได้เช่นกัน สำหรับคนที่สนใจวิธี สามารถอ่านวิธีได้จากที่นี่ครับ ECDSA Public Key to Bitcoin Address Conversion

สำหรับคนที่ยังไม่ชินกับชุดอักษร Base58 อธิบายเพิ่มให้นิดนึงละกันว่ามันคือเลขฐาน 58 ที่นำเสนอด้วยตัวอักษร 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz ซึ่งสังเกตว่ามีอยู่ 4 ตัวที่หายไปได้แก่ 0IOl นั่นก็เพราะว่า 0 กับ O และ I กับ l มันดูคล้ายกันมากในบางฟอนต์จนคนอาจจะแยกไม่ออกและเกิดใช้งานผิดพลาดได้ Base58 ก็เลยตัดสี่ตัวนี้ทิ้งไปจะได้ไม่เกิดปัญหา และนี่คือเหตุผลว่าทำไม Bitcoin Address ถึงเลือกใช้ Base58 ครับ

ดังนั้นที่เราจะใช้กันจริงๆก็จะมีอยู่สองตัวคือ Private Key และ Bitcoin Address สรุปแล้วสมุดบัญชีเลยหน้าตาแบบนี้

โดยเวลาจะให้คนโอนเช็คมาให้บัญชีเรา เราก็แค่เอา Bitcoin Address ให้เค้า เค้าก็จะโอนให้เราได้ทันที (มันเลยชื่อว่า Public Key [Hash] ไง ใครเอาไปใช้ก็ได้) ส่วน Private Key เราจะเอาไว้เคลมว่าเช็คใบนั้นเป็นของเราครับก็เลยต้องเก็บไว้คนเดียวห้ามให้คนอื่น

เอา Bitcoin Address ไปแจกได้ตามสบาย แต่ตัว Private Key เก็บไว้ดี ๆ นะ นี่ย้ำหลายรอบมาก จะเพราะอะไรนั้นไว้ไปดูหัวข้อถัด ๆ ไป

สำหรับสมุดบัญชีเล่มนี้ในโลกของ Bitcoin เราจะเก็บไว้ในส่วนที่เรียกว่า Bitcoin Wallet กันครับ

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

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

ดังนั้น Bitcoin Wallet จึงเป็นแค่ไฟล์ ๆ หนึ่ง

ก็อย่างที่เห็น Bitcoin Wallet มีไว้เก็บสมุดบัญชี ซึ่งสมุดบัญชีก็มีข้อมูลสำคัญอยู่แค่สองตัวเท่านั้นเองคือ Bitcoin Address และ Private Key ซึ่งมันก็ไม่มีอะไรมาก เป็นแค่ชุดข้อความธรรมดา ๆ (ที่ยาวและอ่านไม่รู้เรื่อง)

ดังนั้นในแง่ดิจิตอลแล้ว Bitcoin Wallet ก็เลยเป็นแค่ไฟล์ ๆ นึงเท่านั้นเองครับ และไฟล์นั้นใครครอบครองไว้ก็จะมีสิทธิ์ใช้เงินที่สมุดบัญชีใน Wallet นั้น ๆ อ้างอิงถึงอยู่ใน Blockchain นั่นเอง

ยกตัวอย่างไฟล์แบบง่าย ๆ ของ Wallet (อันนี้เป็น Pseudo นะ ไม่ใช่ของจริง)

wallet.dat

{
bitcoin_address: "1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz",
private_key: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
}

และเมื่อมันเป็นแค่ไฟล์ ๆ นึง เราก็จะรู้ละว่าเจ้า Wallet นี้เลยถูกสร้างไว้ที่ไหนก็ได้

Bitcoin Wallet วางอยู่ที่ไหนในโลกจริง ?

ก็ Bitcoin Wallet มันก็เป็นแค่ไฟล์นี่นา ดังนั้น Bitcoin Wallet จึงจะอยู่ที่ไหนก็ได้ ขอแค่มีไฟล์นี้ก็สามารถแสดงความเป็นเจ้าของ Bitcoin ตาม Private Key ได้เหมือนกัน

ดังนั้นจริง ๆ แล้ว Bitcoin Wallet จะวางไว้ที่ไหนก็ได้ที่สามารถบันทึกข้อมูลเป็นดิจิตอลได้ครับ เช่น

Bitcoin Wallet บนคอมพิวเตอร์

ลง Bitcoin Client บนคอมพ์แล้วมันจะสร้าง Bitcoin Wallet พร้อมสมุดบัญชีขึ้นมาให้พร้อมบันทึกเป็นไฟล์ไว้ในคอมพ์ จากนั้นก็เริ่มเชื่อมต่อกับ Bitcoin Network และเริ่มทำงานได้ทันที

Bitcoin Wallet บนมือถือ

เหมือนคอมพ์แต่กลายเป็นมือถือแทน ลง Bitcoin Client ไว้บนมือถือ ก็จะได้ Bitcoin Wallet เป็นไฟล์อยู่ในมือถือ ทำงานร่วมกับซอฟต์แวร์เพื่อเข้าสู่ Bitcoin Network ได้ทันที

Bitcoin Wallet บน Thumbdrive

เอ๊ะ แล้วแบบนี้ลง Bitcoin ใน Thumbdrive ได้มั้ย ? ก็ต้องได้สิ ! เสียบ Thumbdrive ไว้กับคอมพ์แล้วบันทึก Bitcoin Wallet ใส่ Thumbdrive ไว้ คราวนี้ Wallet ไม่ได้อยู่กับคอมพ์ละนะ แต่อยู่กับ Thumbdrive แทน พกติดตัวไปได้เล้ย

Bitcoin Wallet บนอุปกรณ์เฉพาะทาง (Hardware Wallet)

ตอนนี้ก็เห็นละว่าจริงๆให้เป็นอุปกรณ์ดิจิตอลชนิดไหนก็ใส่ Bitcoin Wallet ได้ ไม่ต้องแปลกใจ มันเลยมีคนผลิต Hardware ที่เอาไว้บรรจุ Bitcoin Wallet โดยเฉพาะอีกด้วย ดูไปดูมาก็คล้าย Thumbdrive ต่างตรงอุปกรณ์พวกนี้จะมีกลไกป้องกันความปลอดภัยอยู่ด้วย

Bitcoin Wallet บนเว็บ (Online Wallet)

ในเมื่อ Bitcoin Wallet มันก็เป็นแค่ไฟล์ ส่วน Web Server มันก็เป็นแค่คอมพ์เครื่องนึงเหมือนกัน ดังนั้น Bitcoin Wallet ก็เลยสามารถสร้างไว้บน Web Server ได้เช่นกัน เวลาใช้งานก็ต้องออนไลน์และทำธุรกรรมผ่านเว็บ

ซึ่งแน่นอนว่า Bitcoin Wallet นี้จะไม่ได้อยู่ในอุปกรณ์ใด ๆ ของเราเลย แต่เราจะฝากไว้บนเว็บแทน เราก็เลยสามารถเข้าใช้จากที่ไหนก็ได้ Wallet แบบนี้เลยได้รับความนิยมมากทีเดียว มีผู้ให้บริการ Online Wallet อยู่เยอะมาก ที่ดัง ๆ ก็ blockchain.info ครับ

Bitcoin Wallet บนกระดาษ ! (Paper Wallet)

อันนี้เท่ ! ในเมื่อ Bitcoin Address และ Private Key มันก็เป็นแค่ข้อมูลจำนวนนึง ก็พิมพ์มันออกมาเป็นกระดาษเลยสิ ! พร้อมเปิดวิธีการนำเข้าสู่ระบบดิจิตอลให้ง่ายที่สุด ... QR Code นั่นเอง จึงได้เป็นกระดาษออกมาแบบด้านบน

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


นี่ยังไม่หมดแค่นี้ จะเห็นว่ามันไม่มีตายตัวนะว่า Bitcoin Wallet จะอยู่บนไหนได้บ้าง ขอแค่มันบันทึกข้อมูลได้และนำมันเข้าสู่ระบบดิจิตอลง่าย ๆ ก็ใช้งานได้แล้ว จะทำ Bitcoin Wallet บนศิลาจารึกก็ได้ถ้าใจนี้ดถ้าเกิดทำอุปกรณ์ที่วาง Bitcoin Wallet ไว้หายจะเกิดอะไรขึ้น?

สมมติว่าเก็บ Bitcoin Wallet ไว้ในมือถือ แล้วดั๊นนนนทำมือถือหาย จะเกิดอะไรขึ้น ?

สิ่งที่จะหายต่อไปคือฉิบครับ ... ฉิบหายยยยยย แน่นวลลลล

เพราะสิ่งเดียวที่เอาไว้ยืนยันว่าเราเป็นเจ้าของใน Bitcoin ก้อนนั้น ๆ ก็จะหายไปพร้อมมือถือด้วย

นี่คือเหตุผลว่าหลังจากที่เราสร้าง Bitcoin Wallet มาแล้ว เราจะต้องทำการ Backup เจ้าไฟล์ wallet เก็บไว้ให้ดี ๆ เช่น ก็อปใส่ Thumbdrive ไว้ 2-3 อัน เพื่อกระจายความเสี่ยงครับ

แต่ข้อควรระวังคือ Thumbdrive ที่เรา Backup ไว้นั้นก็มีข้อมูลสิทธิ์ในการใช้ Bitcoin ของเราอยู่นะ ดังนั้นเก็บไว้ดี ๆ หากโดนขโมย Thumbdrive ไปแล้วคนรู้ว่ามันคืออะไรก็วอดวายเหมือนกัน โดนขโมยเงินหมดตัวแน่นอน

ทำยังไงให้ Bitcoin Wallet ในอุปกรณ์ต่าง ๆ Secure ขึ้น?

ก็จะเห็นว่า Private Key ที่เราเก็บไว้มันเป็นข้อมูลที่เซนซิทีฟมาก ตกอยู่ในมือใครเค้าก็เอาเงินไปใช้ได้เลยหมดบัญชี (เพราะ Private Key เปรียบเสมือนลายเซ็น มีไว้ก็สามารถโอนเงินออกจากบัญชีนั้น ๆ ได้ทันที)

แล้วจะทำยังไงให้ Secure ขึ้น?

Bitcoin Client หลาย ๆ ตัวก็เลยใช้วิธี Encrypt Private Key ไว้โดยใช้ Password เป็น Key เช่น จากเดิม

{
bitcoin_address: "1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz",
private_key: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
}

ก็กลายเป็น

{
bitcoin_address: "1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz",
private_key: "LEORNAUMPWO@(!UOJFOW(*!I_)[email protected] POU!*()"
}

และ Private Key นี้จะใช้งานไม่ได้ ต้องเอา Password มาปลดล็อคก่อนถึงจะกลับกลายเป็นค่าเดิมและใช้งานจริงได้อีกที ต่อให้โดนขโมยไปก็ไม่กลัวแล้วป่ะแบบนี้ เวลาจะ Backup ก็ Backup แบบนี้แหละ สบายใจดี

Password ก็ไม่ได้ถูกบันทึกไว้ตรงไหน อยู่ในหัวของเจ้าของบัญชีเอง ดังนั้นก็ไม่ง่ายละครับที่จะมีใครถอด Private Key ออกมาได้ ยกเว้นตั้งไว้ว่า 12345 ... ก็เอาที่สบายจายยยยย

ส่วนใครลืม Password ... ไม่รู้แล้วเว้ยเฮ้ย

ข้อดีข้อเสียของ Bitcoin Wallet บนอุปกรณ์และบนเว็บ

ก็จะเห็นได้ว่า Bitcoin Wallet จะมีทั้งแบบวางไว้บนอุปกรณ์เราเองกับไปวางไว้บนเว็บ

ซึ่งเว็บที่ว่านี้ก็คือผู้ให้บริการต่าง ๆ เช่น Blockchain.info, GreenAddress เป็นต้น สองแบบนี้มีข้อดีข้อเสียยังไงบ้าง?

Bitcoin Wallet บนอุปกรณ์เราเอง

ข้อดี

- ทุกอย่างอยู่ในมือเรา ไม่ได้เอาไปฝากไว้กับใคร

- ปลอดภัยกว่าถ้าวาง Secure พอ (เช่น Encrypt ไว้อย่างตัวอย่างด้านบน)

ข้อเสีย

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

- ถ้าหายแล้วไม่ได้ Backup ไว้ เงินก็จะหายไปตลอดกาล ที่เจอว่าพลาดกันบ่อย ๆ คือลง Bitcoin Wallet ไว้บนมือถือแล้วทำมือถือหายไม่ก็ไป Factory Reset มือถือ ก็หมดกันเลยทุก BTC ที่มีอยู่

- ถ้าใช้ Bitcoin Client กากกา (มีที่วางไฟล์แบบเดาได้หรือไฟล์ไม่ได้ Encrypt ไว้) หากติดไวรัสที่สร้างมาเพื่อขโมย Bitcoin Wallet เงินก็อาจจะหายไปเมื่อไหร่ก็ได้โดยเราไม่รู้ตัว อันนี้แต่ก่อนก็เจอกันบ่อยเหมือนกัน แต่เดี๋ยวนี้ Client กากกามีน้อยลงแล้ว

- ถ้าใช้ Bitcoin Client ที่สร้างมาด้วยความไม่ประสงค์ดี เค้าก็สามารถแอบเอา Private Key เราไปเก็บไว้ก็ได้เช่นกัน

Bitcoin Wallet บนเว็บ

ข้อดี

- เข้าถึงจากที่ไหนก็ได้ ไม่ต้องพกอุปกรณ์อะไร

- ไม่มีวันหาย (ถ้า Server ไม่โดนบอมบ์อ่ะนะ)

- ถ้าผู้ให้บริการเชื่อถือได้ก็จะ Secure มาก เช่น Encrypt Key เราไว้หมดโดยใช้ Password ที่ไม่มีอยู่ในระบบเป็น Key หรือ Salt

ข้อเสีย

- มันเป็นการฝาก Bitcoin Wallet ไว้กับใครก็ไม่รู้ แปลว่าเค้ามีสิทธิ์จะทำอะไรกับ Wallet เราก็ได้นะถ้าเค้าไม่ซื่อตรง

- ถ้าผู้ให้บริการเป็นคนไว้ใจไม่ได้ วันดีคืนดีเค้าอาจจะปิดบริการแล้วโอนเงินเราไปให้ตัวเองหมดก็ได้นะ

- เราไม่มีทางรู้เลยว่าเค้าเก็บ Secure แค่ไหน ถึงเค้าจะโม้ว่า Secure มากก็ตามก็อาจจะมีช่องก็ได้

ใช้งานแบบไหนสบายใจสุด ?

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

ส่วนถ้าใช้แบบบนเว็บ ยังไงก็อย่าลืม Backup พวก Key จากเว็บมาด้วยนะครับ เว็บพวกนี้ส่วนใหญ่จะมีให้ Export ออกมาได้

รูปแบบจริงของ Bitcoin Transaction และวิธีการใช้งาน Private Key/Bitcoin Address

จากบล็อกที่แล้วเราจะเห็นว่าเราจะจับยัด Transaction ทั้งหลายในช่วงเวลานั้นไว้ใน Block กัน

คำถามคือหน้าตาจริง ๆ ของ Transaction นั้นเป็นยังไง และเราจะใช้ Private Key/Bitcoin Address กันในท่าไหนในแง่ Technical

ซึ่งแน่นอน บล็อกนี้มันเรื่องของ Bitcoin ดังนั้นเอานี่ไปดูเลยยย หน้าตาของ Bitcoin Transaction ของจริงในรูปแบบ JSON คร้าบผม แท่แด๊นนนน

{
   "ver":1,
   "inputs":[
      {
         "prev_out":{
            "index": 0,
            "hash":"15db1694829e7d1c62614fa6dd3ea109c74ec8d4793c3f989ae986e11b619b8d"
         },
         "script":"483045022100a1dd1c583de3a59eb86770b3c9739331473ee7b4afdd337f7de2945f9b05186502200a6c446438422136952e69420655343307073ce570ad47a69194ff9450e2ecf0014104379986a2e38e743a08351723566d986de0f88482cafa07f519fb0495ff696ca931cf68092c2ae09f751b32c983803151b4485dbf77299772ccdcf6c74f2968f6"
      }
   ],
   "out":[
      {
         "addr":"1BFHfZRjgDGbP22hoe3cVKyqqGy28GWtNP",
         "value":8600000,
         "script":"76a9147064fe0d13fed7e3ecf7188339740c15fe15d47888ac"
      }
   ],
   "lock_time":0,
   "size":224,
   "vin_sz":1,
   "hash":"aff93d6d1dccb453b52818e931b6435b2ef84b3c386353cd9b027cd7323f5155",
   "vout_sz":1
}

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

ส่วนตัวเงิน (value) ก็จะอยู่ในหน่วย Satoshi ซึ่งมีค่าเท่ากับ 1 ส่วนร้อยล้าน BTC ดังนั้น 8600000 ในข้อมูลข้างบนก็หมายถึง 0.086 BTC นั่นเอง

ส่วน hash คือค่า Hash ที่ Unique และเอาไว้อ้างอิงถึง Transaction นี้ อย่างเช่นในกรณีนี้ค่า aff93d6d1dccb453b52818e931b6435b2ef84b3c386353cd9b027cd7323f5155 ทำให้เราสามารถกดดูรายละเอียด Transaction นี้ใน Blockchain ได้จาก ลิงก์นี้ใน Blockchain.info

คราวนี้คำถามที่หลาย ๆ คนสงสัยว่า Bitcoin Address และ Private Key จะถูกใช้ตรงไหน คำตอบก็อยู่ตรงนี้นี่แล

วิธีที่ผู้โอนเขียนมอบสิทธิ์ในบิตคอยน์เพื่อให้มีแค่ผู้รับเงินเท่านั้นที่ใช้เงินก้อนนี้ได้

เริ่มจาก out ก่อนเลย การโอนไปยังบัญชีปลายทาง อย่างที่เราเคยอธิบาย เราต้องใช้อะไรในการอ้างอิงคนรับครับ ? ถูกต้องงงง Bitcoin Address นั่นเอง แค่มีรหัสตัวนี้ เราก็สามารถระบุผู้รับได้อย่างแม่นยำ เบื้องต้น Transaction ฝั่งผู้รับ (out) จะมีหน้าตาแบบนี้

   "out":[
      {
         "addr":"1BFHfZRjgDGbP22hoe3cVKyqqGy28GWtNP",
         "value":8600000
      }
   ]

ก็สังเกตดู มีระบุไว้เรียบร้อยว่าคนรับคือ 1BFHfZRjgDGbP22hoe3cVKyqqGy28GWtNP

แต่ระบุแค่นี้ยังไม่พอ คนที่โอนเงินจะต้องเขียนโน้ตไว้ด้วยว่า

"เราขอมอบเงินนี้ให้กับผู้ที่ถือ Private Key ที่ใช้งานเข้าคู่กับเจ้า Public Key Hash นี้เท่านั้น"

ดังนั้น Transaction จึงต้องมีกลไกในการตรวจเช็คได้ว่า Public Key Hash และ Private Key เข้าคู่กัน และกลไกที่ Bitcoin เลือกใช้คือ Pay to Public Key Hash (P2PKH) ครับ

โดย P2PKH จะมีสองส่วนหลัก ๆ ในการทำงาน

1) ส่วนที่ผู้โอนเขียนโน้ตทิ้งไว้ให้ผู้รับ (ก็คือเจ้าด้านบนนี้นี่แหละ)

2) ส่วนที่เอาไว้ยืนยันว่า Private Key เข้าคู่กับโน้ตที่คนโอนเขียนทิ้งไว้

ซึ่งทั้งสองส่วนมันเหมือนการเขียนโค้ดทิ้งไว้ใน Transaction ในระบบนี้เราเลยเรียกมันว่า Script ครับ

เอาส่วนแรกก่อนละกัน ส่วนแรกที่เป็นการเขียนโน้ตทิ้งไว้ใน out ฝากไว้ให้ผู้รับ Script ส่วนนี้มีชื่อเรียกอย่างเป็นทางการว่า Public Key Script หรือ scriptPubKey ซึ่งก็คือ Script ฝั่งที่ใช้ Public Key ครับ

ซึ่งการสร้าง Public Key Script จริง ๆ มันก็ไม่ใช่อะไรซับซ้อน สิ่งที่ต้องใช้ก็มีแค่ Public Key Hash ที่ได้จากเราไปตัวเดียวเท่านั้น แล้วอะไรคือ Public Key Hash หละ ? เราให้เค้าไปตอนไหน ?

ลองนึกย้อนนนนนดูดี ๆ จะรู้ว่า Bitcoin Address จริง ๆ แล้วคือ Public Key Hash ครับ

เพียงแต่ถูกจัดเรียงออกมาให้อยู่ในรูปที่อ่านออก (Base58) แต่ตัว Public Key Hash จริง ๆ จะอยู่ในรูปเลข Base256 ธรรมดา ๆ ดังนั้นเราก็แค่จับแปลงกลับจาก Base58 เป็น Base256 ก็เป็นอันเรียบร้อยแล้ว

ซึ่งถ้าย้อนไปดู ขั้นตอนที่เราเปลี่ยน Public Key เป็น Bitcoin Address มันก็คือการทำย้อนกลับจากขั้นตอน 9 กลับเป็นขั้นตอน 8 นั่นเอง แต่ขั้นตอนที่ 8 ก็ยังมีสิ่งแปลกปลอมเข้ามาปะปนอยู่นิดหน่อยก็คือเจ้า Checksum 4 ไบต์หลัง ดังนั้นหลังจากแปลง Base58 เป็น Base256 เรียบร้อยแล้วตัด 4 ไบต์หลังซึ่งเป็น Checksum ทิ้งก่อนด้วย จากนั้นนำเสนอออกมาเป็นตัวเลขเลขฐาน 16 ก็เป็นอันเสร็จพิธีจ้า

อย่างเช่นในกรณีนี้ 1BFHfZRjgDGbP22hoe3cVKyqqGy28GWtNP จะถูกแปลงได้เป็น

7064fe0d13fed7e3ecf7188339740c15fe15d4784988361c

และตัด 4 ไบต์หลังที่เป็น Checksum ทิ้งได้เป็น

7064fe0d13fed7e3ecf7188339740c15fe15d478

ซึ่งเจ้านี่คือ Public Key Hash ครับ แค่นี้เลย ง่ายและตรงไปตรงมามาก

อันนี้เป็นโค้ด PHP ในการแปลงจาก Base58 ให้กลายเป็น Base256 ในรูปแบบ Hexadecimal เผื่อใครอยากลองเล่น

composer.json

{
    "require": {
	"brick/math": "*"
    }
}

hash.php

<?php

require_once('vendor/autoload.php');

use Brick\Math\BigInteger;
use Brick\Math\RoundingMode;

class Base58
{
	static public $alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";

	public static function decode($base58) {
		$int_val = BigInteger::of(0);
		for ($i = strlen($base58) - 1, $j = BigInteger::of(1), $base = strlen(self::$alphabet); $i >= 0; $i--, $j = $j->multipliedBy($base))
			$int_val = $int_val->plus($j->multipliedBy(strpos(self::$alphabet, $base58{$i})));
		return $int_val;
	}
}

echo Base58::decode('1BFHfZRjgDGbP22hoe3cVKyqqGy28GWtNP')->toBase(16);

จากนั้นเราจะเขียน Public Key Script ออกมาในรูปแบบนี้

OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

ซึ่งพอเอา Public Key Hash ด้านบนมาใส่ก็จะกลายเป็น

OP_DUP OP_HASH160 7064fe0d13fed7e3ecf7188339740c15fe15d478 OP_EQUALVERIFY OP_CHECKSIG

ทำไมต้องเป็นรูปแบบนี้ ? มันเป็น Script รูปแบบตายตัวของ P2PKH ที่เขียนไว้ให้ฝั่งที่มี Private Key (เจ้าของสมุดบัญชี) เอาไปใช้งานต่อตอนที่จะโอนเงินก้อนนี้ออกไปให้คนอื่นครับ

ส่วน OP_DUP, OP_HASH160, OP_EQUALVERIFY และ OP_CHECKSIG พวกนี้มีค่าคงที่อยู่ สามารถดูได้จาก Bitcoin Wiki: Script ครับ โดย OP ก็คือ Operation นั่นเอง เป็นการทิ้งคำสั่งไว้ใน Transaction ประหนึ่งภาษา Assembly ส่วนคำสั่งพวกนี้จะใช้งานยังไงไว้อธิบายต่อในส่วนของการยืนยันสิทธิ์ความเป็นเจ้าของในหัวข้อด้านล่างครับ ตอนนี้ทำตามที่นาย Satoshi เขียนไปก่อน

และจาก Bitcoin Wiki สุดท้ายจะรู้ว่า OP_DUP = 0x76, OP_HASH160 = a9, OP_EQUALVERIFY = 0x88 และ OP_CHECKSIG = 0xac ก็แค่เอาเลขพวกนี้ไปใส่ไว้ จะได้เป็น

76 a9 7064fe0d13fed7e3ecf7188339740c15fe15d478 88 ac

ส่วนตรงก่อนหน้า <PubKeyHash> จริง ๆ ต้องมี OPCODE เพิ่มอีกหนึ่งตัวด้วยเพื่อบอกว่าให้ใส่ค่าเหล่านี้ลงไปใน Stack (Push) โดยระบุเป็นความยาวของ <PubKeyHash> ซึ่งในที่นี้ตัว 7064fe0d13fed7e3ecf7188339740c15fe15d478 มันมีขนาด 20 ไบต์หรือ 0x14 ก็เลยใส่ 14 ไว้ด้านหน้า <PubKeyHash> ด้วยดังนี้

76 a9 14 7064fe0d13fed7e3ecf7188339740c15fe15d478 88 ac

เป็นอันเสร็จพิธี และเราจะเอาค่านี้ใส่ไว้ประกอบร่วมกับส่วนของ out ใน Transaction ครับ

   "out":[
      {
         "addr":"1BFHfZRjgDGbP22hoe3cVKyqqGy28GWtNP",
         "value":8600000,
         "script":"76a9147064fe0d13fed7e3ecf7188339740c15fe15d47888ac"
      }
   ]

out เสร็จสมบูรณ์แล้วจ้า สังเกตดูว่า script เป็นส่วนนึงของแต่ละไอเทมใน Array ดังนั้นถ้ามีคนรับมากกว่า 1 คน ก็ต้องใส่ค่า Script ที่อิงแต่ละ Bitcoin Address ลงไปในทุกผู้รับด้วยครับ น่าจะมองเห็นภาพกันออกเนอะ

และด้วยเหตุผลนี้ แค่ผู้โอนมี Bitcoin Address ของผู้รับก็สามารถสร้างข้อมูลฝั่ง out ได้แล้วครับ และ Bitcoin Address เป็นแค่ข้อมูล Public จึงไม่มีช่องทางไหนที่จะทำให้คนอื่นขโมยเงินก้อนนี้จากเราไปได้ ก็เหมือนเช็คสั่งจ่ายชื่อนี้ไว้แล้ว คนอื่นก็ขึ้นเช็คไม่ได้นั่นเอง

แล้วถ้าเจ้าของบัญชีต้องการจะขึ้นเช็คหละ ต้องทำยังไง ?

การยืนยันสิทธิ์ในการใช้เงินฝั่งเจ้าของบัญชี

คราวนี้มาถึงฟากการยืนยันว่าเรามีสิทธิ์ใน Bitcoin Address นั้น ๆ นะ แล้วถามว่าเราจะยืนยันกันตอนไหน ? เราก็จะยืนยันความเป็นเจ้าของกันตอนที่จะเอาเช็คใบนั้นไปเขียนเช็คใบใหม่ก่อนโอนให้คนอื่นนั่นเอง

ซึ่งก็คือส่วนของ inputs ครับ

   "inputs":[
      {
         "prev_out":{
            "index": 0,
            "hash":"15db1694829e7d1c62614fa6dd3ea109c74ec8d4793c3f989ae986e11b619b8d"
         }
      }
   ]

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

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

เพื่อให้ดูง่ายหน่อย มันก็เหมือนกับว่าข้อมูล prev_out เขียนว่าแบบด้านล่างนี้ (สำหรับใครที่สนใจ อันนี้เป็น Transaction จริง จิ้มดูได้ที่ Blockchain.info)

   "inputs":[
      {
         "prev_out":{
            "addr":"1MyuemkT4raRPPjhDwd9MyzbBNt9QAwKHc",
            "value":8620000,
            "script":"76a914e625c2b4d9318080563b0f2dbfe40c85f0f848fc88ac"
         }
      }
   ]

ได้มาหมดว่าผู้โอนเป็นใคร เช็คมูลค่าเท่าไหร่พร้อมได้ scriptPubKey มาด้วย แล้วเราจะยืนยันกันยังไงหละว่าเจ้าเช็คใบนี้เป็นของเรา ?

เนื่องจากว่า Script ที่ทางผู้โอนเขียนทิ้งไว้ถูกเขียนด้วย Public Key Hash ที่เราเป็นคนส่งให้เค้าเอง สิ่งที่เราต้องทำก็แค่ใช้ Private Key ที่เข้าคู่กันมายืนยันความเป็นเจ้าของใน Public Key Hash นั้นด้วยกลวิธีทาง Public Key Cryptography

ก็ต้องเขียน Script ทิ้งไว้เช่นกันครับ ซึ่งตรงนี้เราจะเรียกมันว่า Signature Script หรือ scriptSig ครับ โดย scriptSig จะอยู่ในรูปแบบ

<Sig> <PubKey>

แล้ว Sig คืออะไร ? สำหรับคนที่คุ้นเคยกับ Public Key Cryptography อยู่แล้ว บอกได้เลยทันทีว่ามันคือ Digital Signature ครับ โดยใช้คุณสมบัติของ Public Key Cryptography ที่ว่า

Signature หรือข้อความที่ถูก Sign ด้วย Private Key จะสามารถได้รับการยืนยันจาก Public Key ได้ว่าข้อความนี้ถูก Sign มาด้วย Private Key ที่จับคู่กันอยู่

ก็คือยืนยันได้ว่าคนนั้น ๆ มี Private Key จริง โดยที่ไม่ต้องเผย Private Key นั่นเอง และเราจะใช้คุณสมบัตินี้ในการสร้าง Signature ขึ้นมาและใส่เข้าไปใน scriptSig ครับ

โดย Input ของการสร้าง scriptSig จะได้แก่ input, output และ Private Key ที่เข้าคู่กับ Bitcoin Address

ซึ่งกระบวนการเซ็น (Sign) นี้ก็เหมือนกับการเซ็นรองรับว่าข้อความทั้งหมดนี้ถูกต้องนะ และหลังจากนี้จะไม่มีใครเปลี่ยน input หรือ output ได้อีก เพราะถ้าเปลี่ยน ค่า sig (Signature) นี้ก็จะเปลี่ยนไปด้วยครับ

ในบล็อกนี้เราคงไม่เขียนว่า Sign กันยังไง จริง ๆ มันก็เป็นกระบวนการ Sign ธรรมดาโดยใช้กลวิธีใน ECDSA เพื่อสร้าง Signature ที่เรียกว่า secp256k1 signature (Sig) ขึ้นมาครับ จากนั้นก็ต่อท้ายด้วย Public Key (PubKey) แบบเต็มที่ถูกสร้างจาก Private Key อีกที จนได้ออกมาเป็น scriptSig ซึ่งอยู่ในรูปแบบเลขฐาน 16 พร้อมแนบคำสั่งอะไรบางอย่างเข้าไปเหมือนเจ้า scriptPubKey

อย่างในตัวอย่างนี้ scriptSig คือ

483045022100a1dd1c583de3a59eb86770b3c9739331473ee7b4afdd337f7de2945f9b05186502200a6c446438422136952e69420655343307073ce570ad47a69194ff9450e2ecf0014104379986a2e38e743a08351723566d986de0f88482cafa07f519fb0495ff696ca931cf68092c2ae09f751b32c983803151b4485dbf77299772ccdcf6c74f2968f6

ซึ่งสามารถ Breakdown ออกมาเป็น Sig และ Public Key ได้ดังนี้

ก็จะเห็นว่า scriptSig นั้นแบ่งเป็นคำสั่ง (PUSHDATA) ซึ่งจะถูกใช้ตอนยืนยันด้วย ร่วมด้วยข้อมูลสองชุดได้แก่ Signature ที่อยู่ในฟอร์แมต DER และ Public Key แบบเต็มตามที่บอกทุกประการครับ

แล้วเจ้า SIGHASH นั้่นคืออะไร ?

SIGHASH คือ Parameter ที่บอกว่าเราจะ Sign อะไรบ้าง ก็เหมือนกันว่าเราจะเซ็นกำกับอะไรบ้างนั่นแหละ หากส่วนไหนเซ็นกำกับไว้ก็จะแก้ไขไม่ได้อีก แต่ถ้าส่วนไหนไม่ได้เซ็นไว้ก็สามารถถูกแก้ไขในภายหลังได้ สำหรับค่า Default คือ SIGHASH_ALL เป็นการบอกว่า "Sign ทุกอย่างทั้ง Input และ Output ทั้งหมด" ก็คือห้ามเปลี่ยนอะไรเลยนะหลังจากนี้

ก็มีวิธีอื่นอีก เช่น Sign เฉพาะ Input นะ ใครจะเปลี่ยน Output ก็ตามใจ แต่ส่วนใหญ่ไม่ค่อยได้ใช้ แต่รู้ไว้ก็ดีเพราะมันทำได้ ยังไงก็สามารถอ่านเพิ่มได้จาก Signature Hash Types ครับว่ามีอะไรบ้าง

เมื่อได้ scriptSig มาก็สมบูรณ์แบบแล้ว เปรียบเสมือนลูกกุญแจที่พร้อมไขแม่กุญแจ scriptPubKey

การรันสคริปต์ยืนยัน

และนี่คือวิธีการแก้ไขแม่กุญแจครับ เอา scriptSig และ scriptPubKey มาต่อกันและจะได้สคริปต์ที่สมบูรณ์แบบ !

[------scriptSig-----| |-----------------------scriptPubKey-------------------------|
PUSH<Sig> PUSH<PubKey> OP_DUP OP_HASH160 PUSH<PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

เป็นสคริปต์ที่ทำงานจากซ้ายไปขวา ร่วมกับ Stack ตามนี้ครับ

ขั้นตอนที่ 1: Push<Sig> Stack ที่ว่างเปล่าก็เลยมี Sig ถูก Push เข้าไป

Stack: <Sig>

ขั้นตอนที่ 2: Push<PubKey> เพิ่ม PubKey เข้าไปใน Stack อีกตัว

Stack: <Sig> <PubKey>

ขั้นตอนที่ 3: OP_DUP คือสั่งให้ Duplicate Top of Stack ขึ้นมาอีกตัวนึง

Stack: <Sig> <PubKey> <PubKey>

ขั้นตอนที่ 4: OP_HASH160 คือสั่งให้ Hash160 สิ่งที่อยู่บน Top of Stack ซึ่งก็คือ <PubKey> จะได้เป็น <PubKeyHash>

Stack: <Sig> <PubKey> <PubKeyHash>

ขั้นตอนที่ 5: Push<PubKeyHash> ก็ Push มันเข้าปายยย

Stack: <Sig> <PubKey> <PubKeyHash> <PubKeyHash>

ขั้นตอนที่ 6: OP_EQUALVERIFY เช็คว่าข้อมูล 2 ตัวบนใน Stack เท่ากันมั้ย ถ้าไม่เท่ากันก็คือถือว่า Verify ไม่สำเร็จและถือว่า script ตัวนี้ทำงานไม่สำเร็จซึ่งก็แปลว่า Transaction นั้นมั่วไม่สามารถใช้งานได้จริงครับ

แต่ถ้าทำสำเร็จข้อมูลทั้งสองก็จะหายไปจาก Stack และทำงานต่อ

Stack: <Sig> <PubKey>

ขั้นตอนที่ 7: OP_CHECKSIG เป็นตัวสุดท้ายละ ทำสองอย่างคือ

(1) Hash Output, Input และ scriptPubKey

(2) เช็คว่า <Sig>, <PubKey> กับ Hash ในข้อ (1) ว่าทั้งสามตัวเข้ากันมั้ย หากไม่เข้าก็ถือว่า Invalid แต่ถ้าเข้าก็ถือว่าผ่าน

(ใครสนใจลงรายละเอียดสามารถดูวิธีการยืนยันเต็ม ๆ ระดับอัลกอริทึมได้จาก OP_CHECKSIG ครับ)

ซึ่งหากทำผ่านก็พบว่า Stack เหลือทิ้งไว้แค่ true แล้วจ้าาา (ผลลัพธ์ของ OP_CHECKSIG)

Stack: true

แล้วมันหมายความว่ายังไง ? หมายความว่าสำเร็จเรียบร้อย Transaction นั้นถือว่าถูกต้องครับ =)

อันนี้เป็นภาพแบบสรุป Operation ในกราฟเดียว


(ตบมาจาก P2PKH Script Validation)

ก็เป็นอันเรียบร้อยแล้น คราวนี้ทาง Technical ก็น่าจะมองออกแล้วว่าทำไมเราแค่มี Bitcoin Address อย่างเดียวก็สามารถโอนให้คนอื่นได้อย่างปลอดภัยแล้วเพราะจะมีแค่คนที่ถือ Private Key เท่านั้นที่สามารถยืนยันความเป็นเจ้าของได้ ต้องขอบคุณ Public Key Cryptography ที่ทำให้สิ่งนี้เกิดขึ้นได้ครับ ^__^

และก็น่าจะเข้าใจแล้วด้วยเช่นกันว่าทำไม Bitcoin ถึงถูกเรียกว่า Cryptocurrency =D

มีวิธีการยืนยันแบบอื่นอีกมั้ยนอกจาก P2PKH ?

มีครับ แต่ขอไปเล่าในส่วนท้าย ๆ นะ เพราะมันค่อนข้างมึนมาก กลัวจะกระทบต่อความเข้าใจในส่วนอื่น ๆ ที่สำคัญกว่า โอเค งั้นมาต่อเรื่องสำคัญก่อน

รูปแบบของ Block

ตอนนี้ทุกคนน่าจะเข้าใจ Transaction แต่ละตัวแล้ว จะบอกว่าแบบละเอียดยิบเลยหละ คราวนี้ Zoom Out ออกมาที่ภาพใหญ่กว่า

อย่างที่บอกเนอะ ใน Block แต่ละอันจะมี Transactions จำนวนมากอยู่ข้างใน ไม่ได้มีแค่อันเดียว

ดังนั้น Transactions จึงกลายเป็น Array ที่ถูกบรรจุอยู่ในโครงสร้างใหญ่อีกชั้นนึง ซึ่งก็คือโครงสร้างของ "Block" นั่นเอง ดังนี้

{
    "ver":2,
    "prev_block":"000000000000001164214d7b57f6db15b6a354146edc700bef115888ddf558e4",
    "merkle_root":"d2d9daef3bd359ad07b528f856b2115056406e312f912ec4ecde04b3fba7cdf4",
    "time":1364758683,
    "bits":436371822,
    "nonce":2131806299,
    
    "tx": [Array-of-Transactions],

    "hash":"000000000000004171dd30130fce7750df2727af7fff99960c74ac06a8eb2353",
}

โดย ver, prev_block, merkle_root, time, bits และ nonce เป็นสิ่งที่เราเรียกว่า Block Header ครับ มีขนาดทั้งหมด 80 ไบต์ ทุกกล่องจะมีขนาดเท่ากันหมด โดย prev_block และ merkle_root จะเป็นสองตัวที่มีขนาด 32 ไบต์ ส่วนอีกสี่ตัวที่เหลือมีขนาดตัวละ 4 ไบต์ครับ

ส่วน tx ก็คือ Array ของ Transactions นั่นเอง

สุดท้าย hash คือผลจากกระบวนการ Proof of Work (การงมเข็ม) ในโลกดิจิตอลครับ การจะได้เลขนี้มีนั้นไม่ง่าย เดี๋ยวจะอธิบายในหัวข้อถัดไป

และเมื่อใดก็ตามที่ Block มีคุณสมบัติเหล่านี้

- Transactions ทุกตัวสมบูรณ์แบบไม่มีปัญหาใด ๆ

- มี Block Header ที่ถูกต้อง

- มีค่า Hash ที่เป็นคำตอบอย่างถูกต้องของโจทย์ Proof of Work

ก็จะได้ Block ที่สมบูรณ์แบบที่พร้อมปล่อยให้ทุกคนเอาไปใช้งานได้ครับ

คราวนี้คงมีข้อสงสัยถึงหลาย ๆ ค่าใน Block ไม่ต้องกังวลไป บล็อกนี้เราจะพามาคลายข้อสงสัยกันทีละตัวแน่นอน แต่ก่อนจะไปต่อกัน ยังมีตัวเลขวิเศษเลขนึงในระบบ Bitcoin ที่ต้องรู้เพื่อที่จะอ่านส่วนอื่นรู้เรื่อง ค่านั้นคือ ...

Magic Number: ระยะเวลาที่ใช้ในการสร้าง Block แต่ละก้อน

ระบบ Bitcoin มีกลไกบางอย่างควบคุมอยู่เพื่อให้ Block แต่ละอันถูกสร้างมาด้วยระยะเวลาเฉลี่ย 10 นาที ส่วนกลไกที่ว่านั้นทำงานยังไง ไว้ไปอ่านรายละเอียดอีกรอบนึงด้านล่างครับ

สิ่งสำคัญที่ต้องรู้ตอนนี้คือ

Block ใหม่จะถูกสร้างขึ้นมาเพิ่มทุก ๆ 10 นาที

ซึ่งค่านี้จะทำให้เราสามารถประมาณเวลาเหตุการณ์หลาย ๆ อย่างได้ต่อจากนี้

ก็แค่นี้แหละ ไม่มีอะไรมาก โอเค พอรู้ตัวเลขวิเศษค่านี้แล้ว เราจะมาพูดถึงเรื่อง Transaction ที่อยู่ในกล่องต่ออีกหน่อยนึง

ตอนนี้เรารู้แล้วแหละว่า Transaction แต่ละอันหน้าตาเป็นยังไง มี inputs มี out เนอะ และแต่ละ Transaction ก็ถูกรวมไว้อยู่ในกล่องอ่ะเนอะ แต่จริง ๆ แล้วในแต่ละกล่องไม่ได้มี Transaction แค่แบบที่เราอธิบายไปเท่านั้น แต่ยังมี Transaction ประเภทพิเศษอยู่อีกประเภทหนึ่งที่จะถูกรวมไว้ในทุก Block อีกด้วย ไปดูกันว่ามันคือ Transaction สำหรับทำอะไร

เงินก้อนแรกมาจากไหน ? รู้จักกับ Coinbase Transaction

ก่อนจะไปถึงเรื่องสิ่งต่าง ๆ ใน Block Header มีเรื่องนึงที่ต้องแถลงไขให้เข้าใจ

หนึ่งในสิ่งที่ตั้งใจทิ้งไว้ให้ค้างคาในบล็อกที่แล้วและรู้สึกดีใจมากที่มีคนถามเรื่องนี้มาเยอะมาก

ในเมื่อคนจะโอนเงินออกจำเป็นต้องใช้เช็คใบที่โอนเข้ามาให้เราและก็เป็นแบบนี้ไปเรื่อย ๆ แล้วแบบนี้คนแรกไปเอาเงินที่ไหนมาโอน ? มันเกิดมาจากไหน ?

สำหรับคนที่ไม่ทันได้สงสัยในบล็อกที่แล้ว ตอนนี้อาจจะตาโตวิ้งวั้งเกิดสงสัยขึ้นมาเอาตอนนี้เลย เออหวะ ! มันมาจากไหน !!

อย่างนึงที่ต้องรู้คือ

ระบบ Bitcoin ไม่มีกลไกให้โอนเงินเข้าไปในระบบนะครับ

เงินทุกบิตคอยน์ที่หมุนเวียนอยู่ในระบบ Bitcoin ล้วนเป็นเงินที่เกิดขึ้นในระบบเองทั้งสิ้น เอ๊ะ แล้วอยู่ดี ๆ เงินมันเกิดเองงี้หรอ ? ... ถูกต้องนะคร้าบบบบบ

ระบบ Bitcoin ถูกออกแบบมาให้ "มอบรางวัลแก่ผู้สร้าง Block สำเร็จ เป็น Bitcoin แบบให้เปล่าให้ฟรีจำนวนหนึ่ง" หรือที่เราเรียกว่า Bitcoin Subsidy

พูดง่าย ๆ คือจำนวนบิตคอยน์ในระบบจะค่อย ๆ เพิ่มขึ้นตามเวลาไปเรื่อย ๆ นั่นเอง

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

โดยจำนวนที่มอบให้นี้เริ่มต้นที่ 50BTC ตอนที่ระบบ Bitcoin เริ่มเปิดใช้งาน และจะลดลงทีละครึ่งในทุก ๆ 210,000 บล็อกครับ ปัจจุบันรางวัลนี้ลดลงเหลืออยู่ที่ 12.5BTC

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

รางวัล Bitcoin Subsidy นี้จะถูกมอบให้กับผู้สร้าง Block สำเร็จในรูปแบบ Transaction ที่ใส่ไว้ใน Block ปกตินี่แหละ เพียงแต่ว่า Transaction นี้ได้รับการยกเว้นไม่ต้องอ้างอิง inputs กับ Transaction ใด ๆ ก่อนหน้านี้ และด้วยความพิเศษของมัน Transaction นี้เลยมีชื่อเรียกเฉพาะด้วยว่า Coinbase Transaction หรือ Generation Transaction

และเราจะใส่เจ้า Coinbase Transaction ตัวนี้ไว้เป็น Transaction แรกของ Block เสมอครับ ดังนั้นหน้าตาของ Array tx เลยจะเป็นแบบนี้

"tx": [
    CoinbaseTx,
    Tx1,
    Tx2,
    Tx3,
    ...
]

แต่สำหรับ Block ที่อินดี้ไม่อยากใส่ก็สามารถไม่ใส่ได้เหมือนกัน แต่ไม่เคยมีใครทำเพราะว่าแปลว่า Block นั้น Miner จะไม่ได้อะไรเลย

สำหรับ Coinbase Transaction จะมีหน้าตาค่อนข้างคล้าย Transaction ทั่วไป จะต่างกันก็ตรง inputs เช่น

{
   "ver":1,
   "inputs":[
      {
         "sequence":0,
         "script":"0303ca0664d24f770969abd4b0818b997fff90ef00bae93ec112dec881e4129af273b7f7f34b4ab6bc0100000000000000a4a6d99413d007fe15cd5f06002f425443432f0000000000000000000000000000000000000000000000000000000000000000"
      }
   ],
   "out":[
      {
         "addr":"152f1muMCNa7goXYhYAQC61hxEgGacmncB",
         "value":1264094716,
         "script":"76a9142c30a6aaac6d96687291475d7d52f4b469f665a688ac"
      }
   ],
   "lock_time":0,
   "size":185,
   "vin_sz":1,
   "hash":"f208cd224bd7c63570a207dd1b4557bc5d1a58e5e225619b032e46ced8287158",
   "vout_sz":1
}

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

แต่ไหน ๆ มันก็มีค่าตรงนี้ไว้ให้ใส่แล้วอ่ะเนอะ ถ้าไม่ใส่อะไรลงไปเลยก็น่าเสียดาย ทาง Bitcoin ก็เลยกำหนดให้เราสามารถแนบค่าอะไรบางอย่างลงไปใน script ตัวนี้ได้ด้วย โดยจะอยู่ในรูปแบบ

Push<SomeVal1> [Push<SomeVal2>] [Push<SomeVal3>] ...

ย้ำอีกทีว่าค่าต่าง ๆ เหล่านี้ไม่ได้ถูกใช้ในการยืนยัน Transaction แต่อย่างใดนะครับ แต่จะใช้งานกันตรงไหนเดี๋ยวไปดูกันอีกที ตอนนี้ต๊ะไว้ก่อน

คราวนี้หายสงสัยแล้วเนอะว่าเงินก้อนแรกมาจากไหน ก็นี่แหละครับ Coinbase Transaction

อ๊ะ อ๊ะ อ๊ะ อ๊ะ มีคนสงสัยอะไรเพิ่มอีกมั้ย ? ... ถ้าเกิด Block นี้อยู่ดี ๆ กลายเป็น Orphan Block และโดนยกเลิกไปหละ จะเกิดอะไรขึ้น ? คำตอบคือ Bitcoin Subsidy ก็จะมลายหายไปด้วยนาจา (ก็มันเป็นแค่ Transaction นึงใน Block ถ้า Block โดนยกเลิกก็ต้องโดนยกเลิกไปด้วยกันทั้งหมดดิ)

ดังนั้นในระบบ Bitcoin ก็เลยตั้งกฎไว้ว่า หลังจากที่ได้ Bitcoin Subsidy แล้วต้องรออีก 100 Blocks เจ้าของถึงจะเริ่มใช้เงินก้อนนั้นได้ครับ ซึ่งก็ทำให้ปัญหาเหล่านี้หมดไป เย้ เย ก็ไม่นานนะ ไม่ถึงวันก็ใช้ได้ละ (ชั่วโมงนึงสร้างได้ 6 Blocks ดังนั้น 100 Blocks ก็ใช้เวลาประมาณ 16 ชั่วโมงครึ่ง)

จำนวน Bitcoin รวมก็เลยจะสิ้นสุดที่ 21 ล้าน BTC

ก็จะเห็นว่าทุกครั้งที่มี Block ใหม่เกิดขึ้น จำนวน Bitcoin ไหลเวียนในระบบก็จะเพิ่มขึ้นเรื่อย ๆ จาก Bitcoin Subsidy แล้วอย่างงี้มันจะมีสิ้นสุดมั้ย ?

แน่นอนว่ามีสิ้นสุดเพราะ Bitcoin Subsidy จะลดลงทีละครึ่งในทุก 210,000 Blocks หรือทุก ๆ 4 ปีนิด ๆ สุดท้ายเลยได้เป็นกราฟลู่เข้าสู่ 21 ล้าน BTC แบบนี้

และหากทุกอย่างเป็นไปแบบอุดมคติ Block สุดท้ายที่มี Bitcoin Subsidy จะสิ้นสุดที่ปี 2140 แต่ก็อาจจะก่อนหน้านั้นก็ได้เพราะเหมือนหลาย ๆ อย่างมันไปเร็วกว่าที่คำนวณไว้ อย่างไรก็ตาม จากกราฟด้านบนก็จะเห็นว่ามันเข้าใกล้ 21 ล้านตั้งแต่ปี 2040 ละ หลังจากนั้น Bitcoin Subsidy ก็ถือว่าน้อยมากจนไม่สามารถใช้เป็นรายได้หลักอีกต่อไป

ซึ่งสาเหตุที่คนออกแบบ Bitcoin Subsidy ให้ลดลงเรื่อย ๆ แบบนี้ก็เพื่อป้องกันปัญหาเงินเฟ้ออันเนื่องมาจาก Bitcoin ในระบบมากเกินไปนั่นเอง

โดยรวมแล้ว Bitcoin ก็เลยเหมือนทอง มีมูลค่าเพราะว่ามันมีจำกัด ถึงจะขุดได้เรื่อย ๆ แต่ก็ขุดได้น้อยลงเรื่อย ๆ เช่นกัน ชะเอิงเงย ~~~~~

มูลค่าของ Bitcoin ก็มีขึ้นลงเหมือนทอง

เนื่องจากกลไกของ Bitcoin เป็นเหมือนทองดิจิตอล มันก็เลยมีราคาขึ้นลงเหวี่ยงหนักกว่าทองอีก นี่คือกราฟราคาในหน่วย USD ตั้งแต่ Bitcoin เปิดตัวมา


(Source: coindesk)

ก็จะเห็นว่า BTC เคยขึ้นไปพีคที่เกือบ $1000 ก่อนจะร่วงลงมาและเริ่มไต่ระดับขึ้นไป ตอนนี้ล่าสุดอยู่ที่แถว ๆ BTC ละ $850 ครับ

ดังนั้นใครสร้าง Block ได้ก็ได้รายได้เยอะไม่ใช่เล่นเลยนะ 1 Block ได้ $10,625 หรือราวๆ 3.8 แสนบาท เพียงแต่ว่าทุกวันนี้มันไม่ได้สร้างง่ายขนาดนั้น การแข่งขันมันสูงมากกกกกก เดี๋ยวไปอ่านด้านล่างถึงรายละเอียดการ Mine อีกทีครับว่าคุ้มไม่คุ้มยังไง

การจ่าย Transaction Fee ให้กับ Miner

เอาหละ ไหน ๆ ก็พูดถึง Coinbase Transaction ละ พูดถึงเรื่อง Transaction Fee ต่อเลยละกัน ถามว่าใน Block จริง เราจะใช้วิธีไหนในการเก็บ Transaction Fee ?

ก็ไม่ได้เอาจากอากาศที่ไหน แอบตบเอาจาก Transaction ทั้งหลายนี่แหละครับ แฮ่ ~~~

สังเกตดู inputs กับ out มีค่าไม่เท่ากัน อย่างด้านบน inputs อยู่ที่ 0.0862 BTC แต่ out มีแค่ 0.086 BTC แล้วอีก 0.0002 BTC ไปไหน ?

นี่แหละครับ ส่วนต่างที่หายไปคือ Transaction Fee ครับ หาก out มีค่ารวมน้อยกว่า inputs ผู้สร้าง Block จะมีสิทธิ์เก็บส่วนต่างในฐานะ Transaction Fee ได้ทันทีครับ

แต่แน่นอนว่าในระบบ Bitcoin ทุกอย่างต้องมีลงบันทึกเป็นลายลักษณ์อักษร แล้วถามว่า Transaction Fee ถูกเขียนไว้ตรงไหนใน Block ?

คำตอบคือ มันไปอยู่รวมกับ Coinbase Transaction ครับ อย่างตัวอย่างด้านบน ลองดู value ตรง out สิ

   "out":[
      {
         "addr":"152f1muMCNa7goXYhYAQC61hxEgGacmncB",
         "value":1264094716,
         "script":"76a9142c30a6aaac6d96687291475d7d52f4b469f665a688ac"
      }
   ],

จะเห็นว่า value มีค่าเท่ากับ 12.64094716 BTC แต่ Bitcoin Subsidy ตอนนี้มันแค่ 12.5 BTC หนิ ? นั่นแหละครับ 0.14094716 BTC ที่เกินมาคือผลรวมของ Transaction Fee ในทุก Transaction นั่นเอง และก็มารวมกับ Bitcoin Subsidy ออกมาเป็นค่าเดียวแบบนี้เลย

และเช่นเดียวกับกรณีด้านบน หาก Block นี้ถูกยกเลิกในภายหลัง Transaction Fee ก็เลยจะถูกยกเลิกไปพร้อมกับ Bitcoin Subsidy ด้วยเน้อ

ก็ตามนั้นคร้าบผม ^__^

ถ้าไม่ยอมจ่าย Transaction Fee จะเกิดอะไรขึ้น ?

Transaction Fee ไม่มีการกำหนดตายตัวว่าต้องจ่ายเท่าไหร่ และคนที่จะกำหนดว่าจะให้เท่าไหร่ก็คือคนโอนนั่นแหละ แค่ให้ค่า out น้อยกว่าค่า inputs ก็คือการระบุ Transaction Fee แล้ว

แล้วถ้าระบุ out กับ inputs เท่ากันหละจะเกิดอะไรขึ้น ? นั่นก็แปลว่าเราไม่จ่าย Transaction Fee ครับ

ซึ่งก็ทำได้นะ แต่ในทางปฏิบัติพวก Miner มักจะให้ Priority Transaction ที่ไม่ยอมจ่าย Transaction Fee (หรือจ่ายน้อย) ให้ต่ำมาก ๆ ๆ ๆ ๆ ดังนั้นหากไม่จ่าย Transaction Fee ก็อาจจะต้องรอเป็นวันหรือหลายวันกว่า Transaction ของเราจะถูก Confirm และจับเข้า Block ครับ

อิพวกทุนนิยม ...

แต่ก็ถูกแล้วแหละ Miner เค้ามีต้นทุนอ่ะนะ ถ้าเกิดใช้เค้าฟรี ๆ ใครจะอยากทำให้

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

Transaction ที่ถูกสร้างขึ้นมาแล้วปล่อยลง Network ไม่จำเป็นจะต้องถูกเอาไปใช้เสมอไปนะครับ อยู่ที่วิจารณญาณของ Miner แต่ละคนล้วน ๆ ว่าจะยัดเข้า Block ให้มั้ย

สำหรับ Standard เรามักจะคำนวณ Transaction Fee ตาม "ขนาดของ Transaction ในหน่วยไบต์" ไม่ใช่คำนวณจากยอด BTC ที่โอนกัน โดยจะอยู่ที่ 0.0001BTC ต่อ 1 kB ซึ่งสำหรับ Transaction ทั่วไปจะอยู่ที่แถว ๆ 500 Bytes

แต่จากการวิจัยข้อมูลที่ผ่าน ๆ มาพบว่า

เรท 0.0002BTC ต่อ 1kB เป็น Transaction Fee ที่ถูกที่สุดที่ทำให้ Transaction ได้รับการ Confirm เร็ว

ดังนั้นในทางปฏิบัติ Transaction Fee ก็จะอยู่แถว ๆ 0.0001 - 0.001 BTC ต่อ Transaction สำหรับ Transaction ทั่วไป แต่ถ้าเป็น Transaction ขนาดใหญ่ (inputs หรือ out เยอะ = จำนวนไบต์เยอะ) ก็อาจจะต้องจ่ายมากเป็นพิเศษหน่อย หากจ่ายไม่สมดุล Transaction ก็จะโดนดองอีกเช่นกันครับ

อย่างงี้รายได้ของ Miner ก็ค่อย ๆ ลดลงตามเวลาสิ ?

ถูกต้องครับ ก็จะเห็นจากกฎเรื่อง Bitcoin Subsidy ว่า เมื่อเวลาผ่านไป จำนวน Bitcoin ที่ได้เป็นรางวัลก็จะลดลงเรื่อย ๆ อย่างเช่นตอนนี้ก็ 12.5 BTC อนาคตก็จะลดเหลือ 6.25 BTC แล้วก็ลดลงอีกทุก ๆ 210,000 Blocks หรือประมาณทุก ๆ 4 ปี (คำนวณเอาเองนะว่าทำไม 4 ปี)

ตอนนี้ก็ได้แต่คาดเดากันไปว่าอนาคตจะเกิดอะไรขึ้นหลังจากที่มันลดลงเหลือน้อยมาก ๆ แล้ว ระบบ Bitcoin จะยังฮิตอยู่มั้ย Transaction Fee จะขึ้นมั้ย จำนวน Miner จะลดลงจนต้นทุนต่ำลงมั้ย บลา ๆ ๆ ๆ ตอนนี้ก็ได้แต่เดากันไปครับ ก็ลองคาดเดากันดูเล่นๆ ได้ฮับ จะอินกับมันมากขึ้น =)

หน้าตาของ Block ณ ขณะนี้

โอเค พาไปดูเรื่อง Transaction ครบถ้วนแล้ว พอรู้เรื่อง Coinbase Transaction แล้ว ตอนนี้ก็จะเห็นละว่าหน้าตาของ Block เป็นแบบนี้

นี่แหละคือกล่องที่ Miner ต้องผลิตขึ้นมา เห็นมะ พอเข้าใจในรายละเอียดแล้วทุกอย่างก็ดูง่ายไปเลย =D

ตอนนี้เรารู้จัก Transaction ครบละ ค่า tx ก็ถือว่าจบไปเรียบร้อยละนะจ๊ะะะะะ ต่อไปถึงเวลาแล้วที่เรามาโฟกัสที่ข้อมูลชิ้นต่าง ๆ ใน Block Header มา ! ฮึบ !!

รู้จักส่วนไหนของ Block Header แล้วบ้าง

Block Header ก็มีอยู่แค่ 6 ตัวอ่ะเนอะ ตัวที่เรารู้แล้วว่าคืออะไรก็มี

version - เวอร์ชั่นของข้อมูลใน Block

prev_block_hash - เป็นค่า block_hash ของ Block ก่อนหน้า ถึงยังไม่รู้ว่า block_hash คืออะไร แต่จากชื่อก็น่าจะเดาออกเนอะว่าเป็นค่า Hash ของ Block แต่ละ Block นั่นเอง และตัว prev_block_hash ก็จะทำให้เรารู้ได้ว่า Block นี้เป็น Block ที่ต่อมาจาก Block ไหน

time - เวลาที่ Block นี้ถูกสร้างขึ้นมาในฟอร์แมต Unix Timestamp

ส่วนอีกสามตัว merkle_root, bits และ nonce นี่ยังไม่รู้ งั้นมาดูความหมายกันทีละตัว เริ่มจากตัวแรก merkle_root

Merkle Root ค่า Checksum ของ Transactions ทั้งหมดใน Block

ก็จะเห็นแล้วเนอะว่าในกล่องมี Transactions อยู่เยอะมาก บางทีอาจจะเป็นหลายร้อยเลย แล้วเราจะทำยังไงให้ชัวร์ได้ว่าหลังจากปิดกล่องไปแล้วจะไม่มีใครมาแก้ข้อมูล Transaction ในกล่องเราได้อีก ?

จริง ๆ สายคอมพ์น่าจะตอบได้ทันทีว่า "ก็ทำ Checksum สิ"

ถูกต้องครับ ที่เราต้องทำคือทำ Checksum พวก Transactions ต่าง ๆ เก็บไว้ใน Header แค่นี้ก็ป้องกันคนมาแอบแก้ Transaction ได้เรียบร้อยแล้ว สำหรับ Bitcoin Transaction นั้นมีการทำ Checksum Transactions ทั้งหมดในกล่องด้วยวิธีที่เรียกว่า Merkle Root ซึ่งก็คือค่า merkle_root ใน Block Header ตามที่เห็นด้านบนโน้นนนนครับ

Merkle Root เป็นวิธีการ Hash ข้อมูลชุดใหญ่ ๆ โดยใช้รูปแบบ Hash Tree ซึ่งจะ Hash Transactions ทั้งหมดใน Block ให้กลายเป็น Hash Value ขนาด 32 ไบต์

วิธีการทำงานของ Merkle Root

Merkle Root ใช้วิธีจับคู่ข้อมูลแล้ว Hash ขึ้นมาเป็นลำดับขั้นสูงขึ้นเรื่อย ๆ แบบ Tree ซึ่งข้อมูลที่ว่าในที่นี้ก็คือ Transaction (Tx) นั่นเอง ยกตัวอย่างเช่นถ้ามี Transaction อยู่ 4 ตัวด้วยกัน (A, B, C, D) เจ้า Merkle Tree จะถูกฟอร์มขึ้นมาเป็นแบบนี้

และเจ้า HABCD นี่แหละครับคือ Merkle Root ผล Hash ร่วมของทุก Transaction ในรูปแบบต้นไม้

หรือถ้ามี 8 ตัวก็จะเป็นแบบนี้

ค่า Merkle Root ของกรณีนี้คือ HABCDEFGH ครับ

แล้วถ้าจำนวนข้อมูลไม่ได้อยู่ในค่า Power of 2 หละ ? เช่น สมมติว่ามีข้อมูลอยู่ 5 ตัว (A, B, C, D, E) ... คำตอบคือยังไงเราก็ต้องจับคู่ครับ แต่ถ้าไม่ครบคู่ให้ตัวที่เหลือจับคู่ตัวเอง ดังนี้

นั่นแหละ เจ้า HABCDEEEE คือ Merkle Root

เพียงเท่านี้เราก็ได้ค่า Checksum ของ Transaction ทั้งหมดแล้ว จากนี้หากใครแก้ไข Transaction ใด ๆ แม้เพียงตัวเดียว ค่า Merkle Root ตัวนี้ก็จะไม่ถูกต้องทันที

ฟังก์ชันในการคำนวณค่า Hash

สำหรับฟังก์ชันที่ใช้ในการ Hash เราใส่เป็นตัวแปรฟังก์ชันไว้เพื่อบอกว่าจะใช้อะไรก็ได้ ขอเพียงว่าถ้าใช้ก็ต้องใช้ร่วมกันทั้งระบบ สำหรับระบบ Bitcoin เค้าเลือกใช้ฟังก์ชัน double-sha256 ครับ

โอเค เข้าใจ Merkle Root แล้ว ต่อไปคือมันมีประโยชน์ยังไง ทำไมถึงเลือกใช้ Merkle Root ในการ Hash Transaction ? จริง ๆ มันมีเหตุผลอยู่ครับ แต่ก่อนจะเข้าใจประโยชน์ตรงนี้ได้ เราต้องเข้าใจการทำของงาน Lightweight Client ก่อน

Recap: Full Node vs Lightweight Client (Thin Client)

บล็อกที่แล้วเราพูดถึง Lightweight Client ไว้แบบไม่ได้ลงรายละเอียดมาก เพราะว่ามันมีความรู้ที่ต้องรู้ก่อนจำนวนนึงถึงจะเข้าใจได้ลึกขึ้น ความรู้ที่ว่านี้คือ "หน้าตาของ Block" ซึ่งในบล็อกนี้เราเห็นแล้วว่ามันมีหน้าตายังไง มันประกอบด้วย Block Header, Transactions และ Hash ของ Block นั่นเอง

สำหรับ Full Node คือ Node แบบเต็มรูปแบบ มีข้อมูล Blockchain ครบทั้งก้อนอยู่ในเครื่อง ซึ่งขนาดก็ไม่ใช่เล่น ๆ เยอะมากเลยหละ ถ้าของ Bitcoin นี่รวมแล้วใส่มือถือราคา 30,000 บาทไม่ได้อ่ะ

ดังนั้น Lightweight Client ก็เลยถูกสร้างขึ้นมาเพื่อให้ประหยัดเนื้อที่ในการจัดเก็บลงไป วิธีก็คือ ยังโหลดมาทั้ง Blockchain อยู่นะ แต่จะโหลดมาแค่ส่วนของ Block Header เท่านั้น ซึ่งดูจากภาพด้านบนจะเห็นว่า Block Header มีขนาดแค่ 80 ไบต์ต่อบล็อกเท่านั้นเอง ซึ่งถ้าคำนวณแล้ว แต่ละปีจะมี Block ถูกสร้างมา 51,120 Blocks ซึ่งจะใช้พื้นที่เก็บเพียง 4.1 MB เท่านั้น

แล้วถ้าเกิด Lightweight Client อยากใช้งานข้อมูล Transaction ไหน (ยกตัวอย่างเช่น เราอยากจะรู้ว่าเรามีบิตคอยน์อยู่เท่าไหร่ เราก็ต้องหา Transaction ทั้งหมดที่เกี่ยวข้องกับเราเนอะ) มันก็จะทำการร้องขอข้อมูลไปยัง Network เพื่อโหลดข้อมูลเหล่านั้นมาใช้แบบ Real Time

ถามว่าทำได้ยังไง ? คำตอบคือตัว Bitcoin Network มีโปรโตคอลเพื่อจัดการสิ่งนี้อยู่แล้วชื่อว่า Bloom Filter อารมณ์เหมือนการ Query ข้อมูลจากฐานข้อมูล มีไว้ให้ Lightweight Client สามารถร้องขอ Transaction ที่ต้องการได้จาก Full Node ใน Network และนี่คือเบื้องหลังการทำงานของ Lightweight Client ครับ

ด้วยเหตุนี้ แอป ฯ ส่วนใหญ่ที่เราใช้งานกันมักจะเป็น Lightweight Client ทั้งนั้น เพราะสำหรับคนทั่วไปเราไม่จำเป็นต้องมีข้อมูลครบทั้ง Blockchain เลย

แล้วใครหละที่ต้องมีครบ ? (ซึ่งก็คือใครที่ต้องเป็น Full Node) ... จะใครซะอีกหละ ก็ Miner ไง เพราะคนจะยืนยัน Transaction ทั้งหมดได้ในพริบตาจำต้องมีข้อมูลทุกอย่างครบไว้ในเครื่อง หากต้องมาส่ง Bloom Filter เพื่อขอข้อมูลแล้วรอยืนยันทีละ Transaction คงไม่ทันกินเป็นแน่แท้ และพวก Miner นี่แหละครับจะเป็นตัวหลักที่คอยส่งข้อมูลและขับเคลื่อน Ligthweight Client ให้ใช้งานได้อย่างสมบูรณ์แบบ

คำถามที่หลาย ๆ คนสงสัยว่า เมื่อเวลาผ่านไป Blockchain มีแต่จะบวมขึ้นเรื่อย ๆ แล้วงี้เครื่องไม่เต็มหรอก็คงได้รับคำตอบแล้วนะครับ ทางออกคือ Lightweight Client นี่เอง =)

สำหรับ Lightweight Client มีชื่ออย่างเป็นทางการว่า Simplified Payment Verification (SPV) หากต้องการคนข้อมูลจาก Google ก็สามารถใช้ชื่อนี้ในการค้นหาได้ครับ

และเจ้า Lightweight Client นี่แหละที่ใช้ประโยชน์ของ Merkle Root อย่างเต็มที่ ช่วยยังไง มาดูกัน

Merkle Root กับการลด Bandwidth การรับส่งข้อมูลลงอย่างมหาศาล

เรื่องมันมีอยู่ว่า มีอยู่หลายครั้งที่ Lightweight Client จำเป็นต้องยืนยันว่า Transaction ที่เรากำลังสนใจ (อาจจะได้มาจากไหนก็ได้) ขอเรียกว่ามันคือ Tx F มีอยู่จริงใน Block ที่กำลังทำงาน อยู่รึเปล่า

ซึ่งแน่นอนว่า Lightweight Client ไม่มีข้อมูลใน Block เลย จะมีก็แค่ Block Header ขนาด 80 ไบต์เท่านั้น

ถ้างั้นทำยังไง ? อ่ะ วิธีแรก ... ส่งไปหา Full Node เฮ้ พวกนาย ช่วงส่งข้อมูลทั้งหมดของ Block นี้มาให้หน่อย

เกิดอะไรขึ้นครับ ? ก็ฟังดูเหมือนจะโอเคนะ แต่หารู้ไม่ว่า Block เนี่ยขนาดมันใหญ่มากเลยนะ อาจจะขนาดถึง 1MB เลย กับการเพื่อยืนยันว่า Transaction อยู่ใน Block รึเปล่าทำไมถึงต้องรับส่งข้อมูลกันเยอะขนาดนี้ด้วย ? มันเปลืองไปมั้ย ?

งั้นเอางี้ วิธีที่สอง ... ส่งไปหา Full Node พวกนายช่วยส่ง "Hash ของแต่ละ Transaction ใน Block ยกเว้นตัว Tx F" มาให้หน่อยสิ แล้วเดี๋ยวเราจะคำนวณหา Hash รวมเองว่าตรงกับ Merkle Root รึเปล่า

ก็คือให้ Full Node ส่งค่าที่วง ๆ ไว้มาให้หน่อย

ถ้า Block มีอยู่แค่ 8 Transactions อย่างด้านบนมันก็พอโอเคนะ ส่งมาแค่ 7 ค่าเองก็คำนวณได้ละ แต่ลองคิดดูว่าถ้าใน Block มีอยู่ 500 Transactions และ Hash แต่ละตัวมีขนาด 32 ไบต์ ... 16,000 ไบต์แหนะ หืมมม ก็เยอะเหมือนกันนะ ถึงจะดีกว่าโหลดมาทั้ง Block เยอะ แต่มันก็ยังเยอะอยู่ดี แล้วมีวิธีที่ดีกว่านี้มั้ยอ่ะ ?

ลองคิดต่อ อ้าว ก็ไหน ๆ มันเป็นรูปแบบ Tree อยู่แล้ว เรารู้อยู่แล้วว่า Tx F หน้าตาเป็นยังไง ถ้ามีอยู่ 8 Transactions ขอให้ Full Node ส่งแบบนี้มาแทนได้มั้ย เราขอแค่ HE, HGH, HABCD มาก็พอ จึงเกิดเป็นวิธีที่สาม ขอมาแค่ Hash ที่เกี่ยวข้อง

ถ้ามีสามตัวนี้ เราก็สามารถคำนวณหาค่า Hash HABCDEFGH ได้แล้วป่ะ ? ตามนั้นครับ และเราจะเรียก Path จาก HF ที่ไต่ไปสู่ HABCDEFGH ได้ว่า Merkle Path ครับ

และนี่คืออิทธิฤทธิ์ของ Merkle Tree วิธีนี้จะทำให้เราสามารถร้องขอข้อมูลโดยใช้เพียง 2*log2(n) ค่าเท่านั้น จะเห็นผลชัดเจนยิ่งขึ้นตอนที่มีจำนวน Transaction สูงมาก เช่น ถ้ามีอยู่ 512 Transactions ก็จะต้องการเพียง 9 Hashes เท่านั้น ผลที่ตามมาคือจะลด Bandwidth การส่งได้อย่างมหาศาลครับ คิดดูสิ จาก 512 ข้อมูลเหลือเพียง 9 ข้อมูลเท่านั้นเองน้าาา

น่าจะเข้าใจกันแล้วนะครับว่าทำไมถึงใช้ Merkle Root ในการ Hash Transactions ทั้งหมดใน Block และมันมีประโยชน์ยังไง ^__^

จบกันไปหนึ่งตัวสำหรับค่าใน Block Header ยังเหลืออีกสองคือ bits และ nonce ซึ่งบอกก่อนตรงนี้ได้เลยว่าค่าทั้งสองเกี่ยวเนื่องโดยตรงกับ Proof of Work ครับ งั้นมาดูกันต่อเล้ย

Proof of Work จริง ๆ เค้าทำอะไรในโลกบิตคอยน์

ในบล็อกที่แล้วเราเทียบการทำ Proof of Work กับการงมเข็มในสระว่ายน้ำเนอะ แล้วในชีวิตจริง Bitcoin Miner เค้าทำอะไรกัน ?

คำตอบคือต้องแก้โจทย์นี้ให้ได้ครับ

จงทำให้ SHA256(SHA256(Block_Header)) มีค่า <= Target

จริง ๆ ก็แค่นี้แหละ ไม่มีอะไรซับซ้อน เอา Block Header ทั้ง 80 ไบต์มา double-sha256 แล้วให้ได้น้อยกว่าค่า ๆ นึง

แต่เผอิ๊ญญญญเผอิญ เจ้า SHA256 นั้นเป็นอะไรที่เดาใจยากมากกกก ปกติมักจะได้เลขออกมาที่มีค่าสูงมากกกกเสมอ การจะหาค่าที่น้อยกว่าที่ตั้งไว้ในโจทย์เป็นอะไรที่ยากมากกกกกกก (ขอใช้คำว่า Extremely Rare) และนี่เลยเป็นโจทย์ Proof of Work ครับ ต้องคอยเปลี่ยน Block Header ไปเรื่อย ๆ จนกว่าค่า Hash ที่ว่านี้มีค่า <= Target

ตอนนี้มีสองคำถามคาใจ ค่า Target คืออะไร ? และ เราจะเปลี่ยนอะไรใน Block Header ได้บ้าง ?

มาที่คำถามแรกก่อน

"ค่า Target คืออะไร ?"

ผู้สร้างระบบ Bitcoin นั้นมีการตั้งความคาดหวังไว้ว่า แต่ละ Block จะต้องใช้เวลา 10 นาทีในการสร้างออกมาเพื่อไม่ให้เร็วหรือช้าเกินไป ก็นะ ถ้าเร็วไปก็ไม่บรรลุผล Proof of Work สิ แต่ถ้าช้าไป Transaction ก็คงไม่ต้องเดินกันพอดี

แต่การจะตั้งค่าที่เป็นค่าคงที่ k ไว้ว่า "จงหา Hash ที่มีค่าน้อยกว่า k" ก็คงไม่ดี ก็ลองคิดดูสิ บางช่วงอาจจะมี Miner มาแข่งหาแก้โจทย์กันเป็นล้านคน แต่บางช่วงอาจจะมีแค่หมื่นคน ถ้าพลังการประมวลผลมันต่างกัน ระยะเวลาที่ใช้ในการหาคำตอบก็จะต่างกันไปด้วย การจะฟิกซ์ค่า Target ไว้เลยให้เป็นค่าใดค่าหนึ่งก็เลยเป็นการออกแบบที่ไม่ดี

สุดท้ายค่า Target เลยถูกตั้งเป็นตัวแปรไว้ และตัวแปรนี้จะถูกคำนวณค่าใหม่ในทุก 2016 Blocks (ประมาณ 2 สัปดาห์) และถูกคำนวณตรง ๆ เลย ถ้า 2016 Blocks ที่ผ่านมาใช้เวลาเกิน 2 สัปดาห์ ก็จะลด Target ลง แต่ถ้าใช้เวลาน้อยกว่า 2 สัปดาห์ก็จะปรับ Target ขึ้น

Note: ค่า Target เริ่มต้นของ Block แรกสุด (เราเรียกว่า Genesis Block) คือ 0x00ffff0000000000000000000000000000000000000000000000000000 และจนถึงตอนนี้ก็มีการปรับเปลี่ยนไปปรับเปลี่ยนมาเรื่อย ๆ หลายร้อยรอบแล้ว

โดยค่า Target ณ ขณะใด ๆ ทุกคนใน Bitcoin Network จะรู้ร่วมกันโดยอัตโนมัติและจะนำค่านั้นมาใช้บรรจุใส่ Block Header ในตัวแปรชื่อ ... bits ครับ

{
    "ver":2,
    "prev_block":"000000000000001164214d7b57f6db15b6a354146edc700bef115888ddf558e4",
    "merkle_root":"d2d9daef3bd359ad07b528f856b2115056406e312f912ec4ecde04b3fba7cdf4",
    "time":1364758683,
    "bits":436371822,
    "nonce":2131806299,
    ...
}

ซึ่งค่า bits จะอยู่ในรูปแบบ Compact ไม่ใช่ค่าที่เอาไปใช้ได้เลยตรง ๆ อย่างในที่นี้ bits มีค่าเท่ากับ 

436371822

หรือในฐาน 16 ก็คือ

0x1A02816E

รูปแบบ Compact (บีบอัด) นี้สามารถแบ่งออกเป็น 1 ไบต์และ 3 ไบต์ดังนี้

1A 02816E

โดย 1A เป็นตัวที่บอกว่า Target มีกี่ไบต์ ในที่นี้ก็คือ 26 ไบต์ (0x1A = 26) เขียนไว้ก่อนเป็น

0x0000000000000000000000000000000000000000000000000000

ส่วนเลข 02816E คือการเอามาแปะทับเลข 000000 ข้างหน้า จะได้ค่าออกมาเป็น

0x02816E0000000000000000000000000000000000000000000000

และนี่คือค่า Target ครับ ให้เปลี่ยน Block Header จนกระทั่งค่า Hash ต่ำกว่าค่านี้ให้ได้ ใครหาได้ก่อนคนนั้นชนะปายยยยย

ส่วนในเรื่องการสื่อสาร โดยปกติเราจะไม่พูดถึง Target แต่จะพูดถึงอีกค่าที่ชื่อว่า "Difficulty" แทนครับ เป็นค่าที่บอกว่า Target ณ ขณะนั้น ๆ ยากแค่ไหน โดยสูตรคือ

ก็จะเห็นว่ายิ่ง Target ต่ำ ความยากก็จะยิ่งสูง และในทางกลับกันก็เช่นเดียวกันครับ

อย่างในกรณีนี้ค่า Difficulty จะอยู่ที่ 6,695,826.28 ครับ (ลองหารกันเองดู) ซึ่งก็จะเห็นได้เลยว่ามันยากกว่าวันแรกที่ Bitcoin ถูกปล่อยเมื่อหลายปีที่แล้วขนาดไหน

คราวนี้กลับมาเรื่องการวิ่งหาคำตอบของ Proof of Work ต่อ เราบอกไปละว่าเราต้องเปลี่ยน Block Header ไปเรื่อย ๆ จนกว่าจะหาคำตอบเจอเนอะ ดังนั้นขอแอบยก Block Header มาอีกรอบ

{
    "ver":2,
    "prev_block":"000000000000001164214d7b57f6db15b6a354146edc700bef115888ddf558e4",
    "merkle_root":"d2d9daef3bd359ad07b528f856b2115056406e312f912ec4ecde04b3fba7cdf4",
    "time":1364758683,
    "bits":436371822,
    "nonce":2131806299,
    ...
}

จะเห็นว่าทุกตัวล้วนเป็นค่าที่ถูกกำหนดไว้คงที่หมดแล้วไม่สามารถปรับเปลี่ยนได้ ยกเว้นตัวเดียวคือ ... nonce จ้า ถูกต้องงงง

nonce เป็นค่าที่ถูกวางไว้ใน Block Header เพื่อการณ์นี้โดยเฉพาะ เพื่อให้เราวนหาค่าไปเรื่อย ๆ จนกว่าค่า Hash จะต่ำกว่า Target ครับ

และนี่แหละ หน้าที่ของ Miner ต้องวนหาค่า nonce นี้ไปจ้าาา

ซึ่ง nonce เป็นตัวเลขขนาด 4 ไบต์ (32 บิต) เลยสามารถมีค่าต่างกันไป 4,294,967,296 ตัวเลข ฟังดูก็เหมือนไม่ยากเนอะ แค่คำนวณให้ครบสี่พันล้านครั้งก็น่าจะได้คำตอบแล้ว

แต่ความจริงชีวิตไม่ได้โรยด้วยกลีบกุหลาบ เพราะถึงจะทำผ่านไป 4 พันล้านครั้งก็อาจจะยังไม่ได้คำตอบแม้แต่คำตอบเดียว

เพราะอย่างที่บอก การจะทำให้ double-SHA256 ออกผลลัพธ์มาเป็นค่าน้อย ๆ นั้นเป็นอะไรที่ยากมากกกกกก

แล้วถ้ายังไม่ได้คำตอบจะทำยังไงหละ ? ไม่มี Header ให้แก้แล้วนี่นา ... ณ จุดนี้เราเลยจะใช้ประโยชน์ของเจ้า scriptSig ใน Coinbase Transaction กันครับ

ยังจำได้มั้ยว่า Coinbase Transaction มีการระบุ script ไว้ แต่ไม่ได้ถูกเอาไปใช้ที่ไหน ยกมาให้ดูอีกรอบ

   "inputs":[
      {
         "sequence":0,
         "script":"0303ca0664d24f770969abd4b0818b997fff90ef00bae93ec112dec881e4129af273b7f7f34b4ab6bc0100000000000000a4a6d99413d007fe15cd5f06002f425443432f0000000000000000000000000000000000000000000000000000000000000000"
      }
   ],

Bitcoin เลยเลือกใช้ประโยชน์จากตัวนี้ในการฝังสิ่งที่เรียกว่า extraNonce เข้าไปครับ โดย extraNonce ก็ความหมายตรงตัวเลย เป็นเลข nonce ตัวนึงซึ่งสามารถปรับเปลี่ยนได้ตามต้องการ หาก nonce ใน Block Header ถูกวนครบแล้วแต่ยังหาคำตอบไม่ได้ เราก็จะมาปรับค่า extraNonce ตรงนี้เพิ่มขึ้น

ถามว่าพอ extraNonce ถูกปรับแล้วจะเกิดอะไรขึ้น ? มันก็มีการเปลี่ยนแปลงของ Transaction ไงครับ และผลที่เกิดขึ้นคือ ค่า Merkle Root จะเปลี่ยนไป นั่นคือ Block Header จะเปลี่ยนไปครับ

และพอ Block Header เปลี่ยนไป คราวนี้เราก็สามารถเริ่มวน nonce ใหม่อีก 4 พันล้านรอบได้ละครับ และถ้ายังวนแล้วไม่เจอคำตอบก็ไปปรับค่า extraNonce อีก เป็นแบบนี้เรื่อยไปจนกว่าจะหาคำตอบเจอ

นี่แหละครับ Proof of Work หละ เห็นรึยังว่ามันต้องใช้พลังประมวลผลมากแค่ไหน กว่าจะหาคำตอบเจอก็โน่นหละครับ 10 นาที น่าจะเข้าใจ Proof of Work ในทางปฏิบัติมากขึ้นแล้วนะครับ เป็นไง สนุกมั้ย =D

จะเกิดอะไรขึ้นหากมี Transaction ใหม่เข้ามาระหว่างทำ Proof of Work

ก็ในเมื่อ Proof of Work มันใช้เวลานานมาก ระหว่างที่ทำ Proof of Work อยู่ก็ไม่แปลกว่ามันต้องมี Transaction ใหม่ถูกส่งเข้ามาเรื่อย ๆ แหละ แล้วจะทำยังไงกับ Transaction พวกนี้ดี ?

จริง ๆ ก็ไม่มีอะไรมากมายครับ ก็ยืนยัน Transaction นั้นแล้วจับเข้า Block ได้เลย !

อ้าว เอ๊ะ อ๋า โอ๋ ... งี้ Merkle Root ก็เปลี่ยนดิ ? ... เปลี่ยนก็เปลี่ยนไปครับ ไม่ใช่ปัญหา เพราะจากด้านบนจะเห็นแล้วว่า double-SHA256 มันเดาใจยากขนาดไหน การที่ใช้ Merkle Root ค่าเดิมก็ไม่ได้แปลว่าจะหาคำตอบได้ การเปลี่ยน Merkle Root ไปเลยไม่ได้ทำให้โอกาสการหาคำตอบเจอลดลงแต่อย่างใด

Proof of Work คือการ Brute Force ครับ วนหาไปเรื่อย ๆ จนกว่าจะ "โชคดี" เจอคำตอบ ถ้ามันต้องอาศัยโชคขนาดนี้แล้ว การที่พระเจ้าส่ง Transaction ใหม่มาก็อาจจะเป็นการให้โชคก็ได้ ...

สาธุสิ รออะไรอยู่

จำนวนการ Hash พร้อมกันทั่วโลกอยู่ที่ ...

เนื่องจากรางวัลอันหอมหวานและยั่วยวน เหล่ามนุษย์ก็เลยตั้งตัวเป็น Miner กันเยอะมาก เราสามารถดูจำนวน Hash รวมต่อวินาทีได้ที่ Hash Rate

ซึ่งก็จะพบว่ามันอยู่ที่ราวๆ ... 21,000,000,000,000,000,000 Hash ต่อวินาทีจ้าาา บ้าไปแล้ววววว แล้วลองคิดดู ต่อวินาทียังเยอะขนาดนี้ แต่กว่าจะมีคนหาคำตอบเจอก็ต้องรอไป 10 นาที คูณกันเอาเองละกันว่าโอกาสจะเจอคำตอบมันน้อยแค่ไหน

ดังนั้นถึงรางวัลจะตั้งไว้สูงมากหลายแสนบาท แต่บางคนพยายามมา 3 ปีก็ยังไม่ได้สัก Block เลยนะ กลายเป็นขาดทุนย่อยยับไปกับค่าไฟแทน ดังนั้นเกมนี้ไม่ได้เล่นกันง่าย ๆ

จึงไม่ต้องแปลกใจ มันเลยมีท่าในการ Mine แบบต่าง ๆ ถูกคิดค้นมาตลอดหลายปีนี้เพื่อเอาชนะเกมนี้กันให้ได้

วิธีการ Mine แบบต่าง ๆ

เนื่องจากว่าการ Mine มันเป็นเกมแบบ Winner-take-all คือคนที่ชนะได้รางวัลไปทั้งหมด ส่วนคนที่แพ้ก็ต้องดูแลตัวเอง #เพลงมา ตอนนี้ก็เลยมีวิธีในการ Mine แบบต่าง ๆ ออกมาเยอะมาก ดังนี้

Mine ด้วยคอมพิวเตอร์

มันก็เป็นแค่การหาค่า Hash อ่ะนะ ดังนั้นคอมพิวเตอร์ก็สามารถคำนวณได้ด้วยเช่นกัน โดยหลัก ๆ จะมีอยู๋ 2 แบบด้วยกัน ได้แก่

- CPU Mining : ใช้ CPU คำนวณ เป็นอะไรที่เบสิคสุดและแน่นอน ... ประสิทธิภาพแย่สุด ๆ คำนวณได้แค่ 0.1 - 20 Mhash ต่อวินาทีเท่านั้นเอง

- GPU Mining : ใช้ GPU (ซึ่งเก่งมากเรื่องงานคำนวณ) ในการหาค่า Hash อันนี้ดีขึ้นมาพอสมควร สามารถคำนวณได้ 100 - 500 Mhash ต่อวินาทีเลย หรือถ้าแรงมากหน่อยก็อาจจะพุ่งไปถึง 1,000-2,000 Mhash ได้ แต่โดยรวมก็ยังถือว่าน้อยมากอยู่ถ้าเทียบกับ Hash Rate รวมทั่วโลก

สรุป ... การ Mine ด้วยคอมพิวเตอร์เลยใช้งานจริงไม่ค่อยได้ ยังไงก็ไม่มีทางชนะเกมนี้ เปลืองไฟเปล่า ๆ

Mine ด้วย USB Bitcoin Miner

ก็ถ้า CPU กับ GPU มันคำนวณช้า งั้นเอานี่ ... อุปกรณ์ USB ที่ถูกสร้างเพื่อ Mine โดยเฉพาะ เพียงแค่เสียบอุปกรณ์นี้ไว้กับคอมพิวเตอร์คุณ มันก็สามารถเริ่มคำนวณให้คุณได้ทันที !


(ภาพจาก YouTube)

จริง ๆ มันก็ไม่มีอะไรหรอก มันเป็นอุปกรณ์แยกที่ทำหน้าที่วนหาค่า Hash ไปเรื่อย ๆ นั่นแหละ แล้วก็สั่งการผ่านคอมพิวเตอร์อีกที อุปกรณ์พวกนี้ราคาถูกมาก แบบ ไม่เกินพันอะไรงี้ แต่สามารถหาค่า Hash ถึงได้หลัก Ghash ต่อวินาทีเลยทีเดียว อย่างตัวในรูปนี้ก็โน่น 2.7 Ghash/s

ถ้าอยากเพิ่มก็ Load Balance ได้ด้วยนะ ...


(ภาพจาก YouTube)

อย่างไรก็ตาม ... ก็ยังน้อยอยู่ดีอ่านะ แหะ ๆ (Ghash/s ยังถือว่าน้อย เศร้าป่ะหละ)

Mine ด้วย FPGA

ก็ถ้าการ Mine ด้วย Hardware คอมพิวเตอร์มันไม่ได้ประสิทธิภาพ งั้นก็ออกแบบชิพเองซะเลย ! มันคืออะไรหละ ? ก็ FPGA ไง (ชิพที่สามารถออกแบบและเขียนโปรแกรมปรับเปลี่ยนการทำงานของ Logic Gate เองได้)

งานนี้ก็เลยมีคนทำบอร์ด FPGA แล้วโปรแกรมให้กลายเป็น Bitcoin Miner แล้วทำออกขาย

ข้อดีของมันคือมันกินพลังงานน้อยกว่า CPU และ GPU มาก แต่ประสิทธิภาพส่วนใหญ่ก็จะอยู่ในหลัก 1-10 GHash/s ซึ่งไม่ถือว่าสูงมากครับ

สำหรับ CPU, GPU และ FPGA Mining ปัจจุบันคนที่ต้องการ Mine แบบจริง ๆ จัง ๆ จะไม่ใช้กันแล้ว เพราะประสิทธิภาพต่ำและการกินไฟค่อนข้างสูงเกินไปนั่นเอง เนื่องจากว่าอุปกรณ์เหล่านี้ไม่ได้เกิดมาเพื่อ Mine โดยเฉพาะ มันก็เลยมีข้อเสียอยู่หลาย ๆ อย่าง

ซึ่งแน่นอน ... มันผ่านมานานขนาดนี้แล้ว มันก็เลยมีคนทำอุปกรณ์เฉพาะทางสำหรับ Mine ออกมาขายเช่นกัน

Mine ด้วย ASIC (เครื่องขุด)

ASIC ย่อมาจาก Application Specific Integrated Circuit หรือพูดง่าย ๆ ก็คืออุปกรณ์ที่ถูกออกแบบมาเพื่อใช้งานเฉพาะ หรือในที่นี้ก็คือการ Mine Bitcoin นั่นเอง

ช่วงราคาก็มีอยู่ตั้งแต่ $100 ยันโน่น $3,000 แต่ประสิทธิภาพนี่โหดเหี้ยมมาก เพราะจะ Hash ได้ในหลัก Thash/s เลย (T = Tera = 1012) และพวกคนที่กะจะหาเงินจากการ Mine จริง ๆ จัง ๆ ก็จะเลือกใช้ ASIC กันครับ

ซึ่งไม่ต้องแปลกใจเลยว่าทำไม Hash Rate รวมของโลกถึงสูงขนาดนี้ ก็เพราะว่าใช้ ASIC กันหมดนี่แหละ

สุดท้ายไม่รู้เหมือนกันว่า Miner จะรวยมั้ย แต่คนขาย ASIC นี่แหละ น่าจะรวยชัวร์ ๆ ละ ...

สำหรับคนที่สนใจว่า ASIC มีตัวไหนน่าสนใจบ้าง ลองไปอ่านดูได้ที่ Mining hardware comparison ครับ

Cloud Mining

มีคนเปิดบริการให้เช่าอุปกรณ์สำหรับ Mine ด้วย เค้าก็จะคิดประมาณว่า 1 GHash/s ต้องจ่ายเดือนเท่าไหร่ ก็แค่จ่ายเงินไป ที่เหลือเดี๋ยวเค้าจะไป Mine ให้ด้วยอัตราที่สัญญากันไว้ ถ้าโชคดีก็สร้าง Block ได้ ถ้าโชคร้ายก็จ่ายเงินฟรี ... อารมณ์เหมือนซื้อลอตเตอรี่อ่ะ 555

อย่างไรก็ตาม ได้ยินข่าวไม่ดีเกี่ยวกับ Cloud Mining มาเยอะ โกงบ้างอะไรบ้าง ดังนั้นก็เลยไม่ค่อยเห็นใครใช้บริการเท่าไหร่ครับ

Mining Pool

เนื่องจากมันเป็นเกม Winner-take-all ที่เดิมพันด้วยเงินที่สูงมาก คนที่ผิดหวังก็เริ่มเยอะขึ้นเรื่อย ๆ เพราะมีโอกาสน้อยมากที่จะชนะเกมนี้ได้

สุดท้ายก็เลยมีคนหัวใสเปิดสิ่งที่เรียกว่า "Mining Pool" ขึ้นมา

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

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

สังเกตดูได้ว่า ผู้สร้าง Block ได้เกินครึ่งเป็น Mining Pool ทั้งนั้น


(ภาพจาก Blockchain.info)

หากใครมี ASIC ก็สามารถเปิดใช้งานต่อกับ Pool ทิ้งไว้แล้วก็รอรับเงินทุกวี่วันได้เลย (แต่ Hash Rate ต้องสูงพอด้วยนะ ต้องเป็นหลัก Thash/s ไม่งั้นก็จะไม่ได้ส่วนแบ่งเลย)

Pool Mining มีให้เลือกใช้หลายที่ แต่ที่ใหญ่ที่สุด ได้รับความนิยมสุดและมีโอกาสสร้าง Block ได้สูงสุดก็คือ AntPool แต่เจ้าอื่น ๆ ก็ยังมีอีกเยอะ ไปอ่านเพิ่มเติมได้จาก Comparison of mining pools ครับ

ค่า Hash ที่ได้เป็นคำตอบจะกลายเป็นค่า Hash ของ Block

เมื่อ Block หาคำตอบเจอแล้ว คำตอบจะถูกบรรจุเก็บไว้ในกล่องด้วย ซึ่งก็คือค่า block_hash นั่นเอง

อันนี้จะกลายเป็นรหัสประจำกล่องไปในทันที หากมีกล่องมาสร้างต่อก็แค่กำหนด prev_block_hash ให้เป็นค่า block_hash ของกล่องนี้ก็เป็นอันเรียบร้อยแล้ว

และด้วยเหตุผลนี้ Blockchain ก็เลยไม่สามารถแก้ไขได้ เพราะถ้ามีใครแก้ Transaction ใดก็ตามในกล่องใดกล่องหนึ่ง ค่า Merkle Root ของกล่องนั้นก็จะเปลี่ยนไป Block Header ก็จะเปลี่ยนไปและสุดท้ายจะส่งผลให้ค่า Hash ต้องเปลี่ยนไปด้วย แต่ด้วยกลไก Proof of Work การหาค่า Hash ใหม่นี้ทำได้ยากมาก หากแก้กล่องนี้เสร็จ ค่า Hash ใหม่ก็จะส่งผลต่อกล่องที่อยู่ด้านล่างด้วย ดังนั้นจึงสรุปได้ว่า มันเป็นไปไม่ได้เลยที่จะแก้ไข Blockchain ทั้งสายได้

นี่แหละครับ Blockchain ... การเก็บข้อมูลแบบกระจายที่ไว้ใจได้ ^__^

Block และ Blockchain สมบูรณ์แบบแล้ว !

ยินดีด้วย เนื้อหายาวมากกว่าจะมาถึงจุดนี้ ตอนนี้เราเข้าใจโครงสร้างของ Block อย่างครบถ้วนสมบูรณ์แบบแล้วจ้าาา

ถ้าเข้าใจทุกส่วนก็น่าจะมองเห็นภาพแบบบรรลุเรียบร้อยแล้วว่า Bitcoin ทำงานยังไง รวมไปถึงว่า Blockchain เจ๋งยังไงครับ

แต่ ... เนื้อหายังไม่จบ ยาวมาขนาดนี้แล้วก็ต่ออีกหน่อยละกัน

ถ้ารู้ Bitcoin Address ก็สามารถ Track ธุรกรรมตลอดชีพได้หมดสิงี้

Blockchain เป็นข้อมูลสาธารณะ ทุกคนถือข้อมูลชุดเดียวกันนี้อยู่ ดังนั้นก็เลยเป็นไปตามนั้นครับ ทุกคนสามารถดูได้ว่า Bitcoin Address ใด ๆ มีการเดินบัญชีอย่างไรบ้างตั้งแต่เริ่มต้น ยกตัวอย่างเช่น เราอยากรู้ว่า 1BQLNJtMDKmMZ4PyqVFfRuBNvoGhjigBKF เคยทำธุรกรรมอะไรมาบ้าง ก็สามารถจิ้มดูได้จาก BitRef.com เลยครับ

เราเรียกสิ่งนี้ว่า Transparency ครับ คือทุกอย่างเปิดเผย แต่อย่างไรก็ตาม โดยปกติแล้ว Bitcoin Address ไม่สามารถบอกตัวตนของคนนั้น ๆ ได้ ซึ่งเราเรียกว่า Anonymity ดังนั้นถึงจะเห็นธุรกรรมแต่ก็ไม่รู้อยู่ดีว่าเป็นใคร

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

จริง ๆ Bitcoin Address ถูกออกแบบมาให้ใช้ครั้งเดียว

เห็นข้อเสียด้านบนก็จะพอเข้าใจว่า ถ้าใช้ Bitcoin Address เดิมตลอดก็จะตรวจสอบได้แบบนี้แหละ

วิธีแก้ไขง่าย ๆ เหมือนกำปั้นทุกดินเลยก็คือ งี้ก็เปลี่ยน Bitcoin Address เรื่อย ๆ สิ

ทำได้มั้ย ? ได้สิ !

และเอาจริง ๆ นี่เป็นสิ่งที่ผู้ออกแบบระบบตั้งใจให้เป็นด้วยครับ คือ

Bitcoin Address ถูกออกแบบมาให้ใช้ครั้งเดียวครับ

แต่เผอิญว่ามันสามารถใช้ซ้ำได้อย่างไม่มีปัญหา (เรียกว่า Address Reuse) คนก็เลยไม่ค่อยเปลี่ยนกัน

แล้วถ้าต้องการให้มันใช้งานได้ครั้งเดียว ในทางปฏิบัติมันทำงานยังไง ? ... เป็นแบบนี้ครับ

1) Alice โอน ChequeA มาให้เราที่ Bitcoin Address A

2) ตอนเราจะเอา ChequeA ไปใช้ก็โอนเงินไปให้ Bitcoin Address ปลายทางตามปกติ แต่เงินทอน (Change) ให้ส่งไปยัง Bitcoin Address B ของเรา

3) ตอนนี้ Bitcoin Address ปัจจุบันของเราคือ B แล้ว หากจะให้ใครโอนเงินมาให้เราก็ให้ตัว B นี้ไป

4) หากมีธุรกรรมที่เราต้องโอนเงินออกก็ทำแบบเดิม คือโอนเงินไปให้ปลายทางและส่งเงินทอนไปที่ Bitcoin Address C

แล้วก็ทำแบบนี้ไปเรื่อย ๆ

ด้วยวิธีนี้จะทำให้ไม่มีใครสามารถ Track ได้เลยว่าเราเคยทำธุรกรรมอะไรไปบ้าง เพราะถ้าเค้ามี Bitcoin Address A ของเรา เค้าก็จะเห็นแค่มีคนโอนเข้าและก็โอนออก 1 ธุรกรรม จบ และเช่นเดียวกันกับ Bitcoin Address B, C, D, E และไปเรื่อย ๆ ครับ และจากการที่ Bitcoin Address มันมีความ Anonymity ก็เลยไม่มีใครสามารถเชื่อมโยงได้ว่า Bitcoin Address A, B, C, D, E เป็นเจ้าของเดียวกัน

และนี่คือวิธีใช้ Bitcoin อย่างปลอดภัยครับ

ความจริงแล้วมันมีอยู่หลายเหตุผลสนับสนุนการกระทำตรงนี้เลยแหละ ตั้งแต่เรื่องของ Privacy ในการตรวจสอบธุรกรรมดูย้อนกลับได้ ไปจนถึงเรื่องของความปลอดภัยใน ECDSA ว่าถ้าวันใดมันถูกแฮคขึ้นมาและแฮคเกอร์สามารถเปลี่ยน Public Key กลับเป็น Private Key ได้ขึ้นมานี่วอดวายเลยนะ (ตอนนี้อาจจะยังทำไม่ได้ แต่อาจจะทำได้ด้วย Quantum Computer ในอนาคต ... Cryptography หลาย ๆ ตัวจะใช้งานไม่ได้เลยในวันที่ Quantum Computer ใช้งานได้จริง)

และ Public Key เราก็เปิดเผยไว้เรียบร้อยในส่วนของ scriptSig ตอนเคลมเช็คใบนั้น ๆ มาใช้งาน ยังจำกันได้มั้ย

scriptSig: <Sig> <PubKey>

ดังนั้นทางที่ดีคือทันทีที่เราเปิดเผย Public Key แล้ว (ก็คือขั้นตอนเคลมเช็คใบนั้น) ก็ยกเลิก Keypair คู่นั้นทิ้งไปเลยแล้วไปใช้ตัวใหม่แทน ซึ่งก็คือ Bitcoin Address และ Private Key ตัวใหม่ครับ

ดังนั้นหนึ่ง Bitcoin Wallet เลยมีได้หลายสมุดบัญชี

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

ซึ่งก็อย่างที่เห็น แต่ละเล่มจะมี Bitcoin Address และ Private Key เป็นของตัวเองไม่ซ้ำกัน ดังนั้นโครงสร้างของ Bitcoin Wallet จากเดิมที่เป็นแบบนี้

{
bitcoin_address: "1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz",
private_key: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
}

ก็จะกลายเป็นแบบนี้ครับ

[
  {
    bitcoin_address: "1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz",
    private_key: "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
  },
  {
    bitcoin_address: "........",
    private_key: "......."
  },
  ...
]

ก็คือจะกลายเป็น Array นั่นเอง

ในทางปฏิบัติเราจะทำกันยังไง ? จริง ๆ อันนี้เป็นเรื่องทางเทคนิคครับ แต่ในชีวิตจริง โดยปกติ Bitcoin Client จะจัดการตรงนี้ให้ครับ ถ้าเกิดเราต้องการเพิ่ม Bitcoin Address ใหม่ก็แค่กดตาม UI ที่เค้าทำไว้ แล้ว Bitcoin Address - Private Key คู่ใหม่ก็จะถูกสร้างและใส่เข้ามาใน Bitcoin Wallet โดยอัตโนมัติ

และตรงนี้สิ่งที่สำคัญที่อยากฝากไว้คือ ทุกครั้งที่มีการเพิ่ม Bitcoin Address ใหม่ก็เหมือนเราเปิดสมุดบัญชีเพิ่ม เราต้อง Backup ไฟล์ wallet.dat ใหม่ด้วยครับ

เพราะหากทำอุปกรณ์หายแล้วไฟล์ที่ Backup ไว้ดันเป็นกระเป๋าตังค์ใบเก่าที่ไม่มีสมุดบัญชีเล่มใหม่ เงินก็หายเหมือนกันนะครับ

นอกจากนั้น ถ้าเกิดเราใช้บริการ Online Wallet ของบางเจ้า เช่น BlockChain.com ทุกครั้งที่มีคนโอนเงินเข้ามา Bitcoin Address ของเราจะถูกเปลี่ยนไปทุกครั้งโดยอัตโนมัติครับ ทั้งนี้หลัก ๆ ก็เพื่อกันไม่ให้คนไล่ดูรายการเดินบัญชีได้นั่นเอง แต่ยังไง Bitcoin Address ตัวเก่าก็ยังโอนเข้าได้อยู่นะ หลักการเหมือนเดิมเป๊ะ

ประเภทของ Wallet

ไหน ๆ ก็เขียนมาซะขนาดนี้แล้ว ก็เอาให้ครบ ๆ ละกัน

จะเห็นว่า Bitcoin Wallet หนึ่งใบสามารถมีสมุดบัญชี (Bitcoin Address - Private) ได้หลายตัว แต่โดยรายละเอียดมันก็มี Bitcoin Wallet อยู่แบ่งเป็น 3 ประเภทด้วยกัน ดังนี้

1) Conventional Wallet

ก็คือ Wallet ที่ Bitcoin Address - Private Key (Keypair) แต่ละตัวมีอิสระต่อกัน ไม่มีความเกี่ยวข้องใด ๆ กัน เป็นการ Random มาล้วน ๆ

Private Key A - Bitcoin Address A
Private Key B - Bitcoin Address B
Private Key C - Bitcoin Address C
...

อันนี้เรียกว่า Conventional Wallet หรือ Wallet แบบธรรมดาครับ

ข้อเสียของวิธีนี้คือเราต้องคอย Backup ไฟล์ wallet.dat เรื่อย ๆ เพราะ Keypair อาจจะถูกสร้างเพิ่มขึ้นมาเมื่อไหร่ก็ได้ หากลืม Backup แล้วทำอุปกรณ์หายก็บ้ายบายเลย

2) Sequential Deterministic Wallet (SD Wallet)

เป็นการสร้าง Private Key ขึ้นมาจาก String (Seed) ตัวหนึ่ง แล้วบวกด้วยตัวเลขไปเรื่อย ๆ เช่น ถ้า Seed คือ Lorem ipsum dolor sit amet ก็จะสร้าง Private Key ทั้งหลายขึ้นมาตามนี้

Private Key A = hex(sha256('Lorem ipsum dolor sit amet 1'))
Private Key B = hex(sha256('Lorem ipsum dolor sit amet 2'))
Private Key C = hex(sha256('Lorem ipsum dolor sit amet 3'))
...

ส่วน Bitcoin Address ก็ถูกสร้างจาก Private Key แต่ละตัวเหมือนเดิมและสุดท้ายก็ถูกวางใส่เป็นคู่ ๆ ไว้ใน Wallet เหมือนตัวบน เอาไปใช้งานได้ทันที

แบบนี้สบายใจได้อย่างนึงขอแค่ Backup เจ้า Seed ไว้ที่เอาไว้สร้าง Private Key ไว้ จากนั้้นถึงจะทำเครื่องหาย ทำไฟล์ wallet.dat หายก็ไม่กังวลละเพราะแค่มี Seed ก็สามารถสร้าง Wallet ขึ้นมาใหม่ได้แล้ว

อ้อ ... แต่อย่าทำไฟล์ Backup Seed หายไปด้วยละกัน ...

3) Hierarchical Deterministic Wallet (HD Wallet)

อยู่ในกลุ่ม Deterministic Wallet เหมือนกัน ก็คือ Keypair ทั้งหลายจะถูกสร้างมาจาก Seed

สำหรับ Seed ใน HD Wallet จะไม่ง่าย ๆ เหมือนกับ SD แล้ว แต่จะถูก Generate ขึ้นมาเป็นเลขขนาด 128 บิต และจะถูกนำมาสร้างเป็น Master Keypair (Private Key / Public Key) ส่วน Keypair ที่เหลือจะถูกสร้างเพิ่มขึ้นเรื่อย ๆ ในรูปแบบ Tree กลายเป็นสมุดบัญชีที่ถูกสร้างขึ้นมาด้วย Master Keypair นั่นเอง

ไม่ลงรายละเอียดมากเพราะวิธีทำแอบซับซ้อน แต่ผลที่เกิดขึ้นคือ แค่ Backup Master Seed หรือ Master Keypair ไว้ตัวเดียวมันก็สามารถสร้าง Wallet กลับมาได้แล้วเสมอ ต่อให้มีสมุดบัญชีงอกเพิ่มขึ้นมาใหม่มากเท่าไหร่ก็ตาม

ความเท่อีกขั้นนึงของ HD Wallet คือ Public Key ก็สามารถงอกเป็น Tree ได้ด้วยตัวเองอีกด้วยโดยไม่ต้องพึ่ง Private Key ส่งผลให้แค่มี Public Key จาก Master Keypair เราก็สามารถสร้าง Bitcoin Address เพิ่มขึ้นเรื่อย ๆ ได้ทันทีโดยไม่ต้องมี Private Key

หากเว็บไหนสนับสนุน HD Wallet เราก็สามารถโยน Public Key ของ Master Keypair เข้าไปเก็บไว้ได้ แล้วเว็บนั้นจะสร้าง Bitcoin Address ตัวใหม่ ๆ ให้เราใช้งานได้ทันทีเองโดยอัตโนมัติ เจ๋งม้าาา

HD Wallet นี้ถูกใช้ในผู้ให้บริการ Blockchain / Bitcoin Client ดัง ๆ หลายตัว เช่น Ethereum รวมถึง BlockChain.com ก็ใช้ HD Wallet เช่นกัน

ภาคผนวก: Block มีขนาดได้ไม่เกิน 1 MB

เริ่มเข้าสู่เนื้อหาส่วนแถม

ข้อมูลนึงที่ต้องรู้เอาไว้สำหรับคนที่อยากจะลงลึกเรื่อง Bitcoin คือ Block แต่ละอันมีขนาดได้ไม่เกิน 1MB เท่านั้น ลองไปจิ้มดูจาก Blocks ของเว็บ BlockChain.info ได้ จะเห็นว่า Block มีขนาดมากสุดอยู่ที่ 999.xx kB ไม่มีอันไหนเกิน 1000 kB มาเลย

และนี่คือเหตุผลว่าถ้า Transaction ไหนไม่จ่าย Transaction Fee ถึงมักจะได้รับการ Confirm ช้า นั่นก็เพราะว่า Block แต่ละอันมีเนื้อที่จำกัดในการใส่ Transaction ถ้าเกิดพี่อินดี้ไม่จ่ายค่าบริการ Miner ก็จะให้สิทธิ์กับคนที่จ่ายก่อนนั่นเอง

ส่วนสาเหตุที่จำกัดไว้ที่ 1 MB ก็เพื่อให้การทำงานโดยรวมมีประสิทธิภาพครับ เพราะหาก Block ใหญ่เกินไปจะทำให้ Full Node ทำงานได้ช้าลง

ภาคผนวก: Blockchain ยังคงงอกอยู่ ตอนนี้ Bitcion Blockchain มีขนาดเท่าไหร่แล้ว ?

เนื่องจาก Blockchain มันเป็นข้อมูลเปิดเผย ดังนั้นเราเลยสามารถดูขนาดของ Bitcoin Blockchain ล่าสุดได้จาก block-size ครับ ซึ่ง ณ วันนี้ (26 ธันวาคม) ขนาดก็อยู่ที่ 96GB เป็นที่เรียบร้อยแล้ว -0-

และก็ยังเพิ่มต่อไป ต่อไป และต่อไป แฮ่ ~~~

ภาคผนวก: ตอนนี้ Blockchain มีกี่ Block แล้ว

แน่นอนว่าดูได้เช่นกันว่าตอนนี้ Blockchain มี Block อยู่กี่ชั้นแล้ว จิ้มดูได้เลยที่ getBlockCount ครับ อย่างตอนที่เขียนบล็อกนี้ก็ 445100 Blocks ครับ และก็จะเพิ่มขึ้นเรื่อย ๆ ประมาณชั่วโมงละ 6 Blocks ตามที่เคยบอกก่อนหน้านี้

ภาพผนวก: วิธียืนยันความเป็นเจ้าของที่ไม่ใช่ P2PKH

แอบ Hint ไว้ด้านบนแล้วว่ายังมีวิธีการยืนยันความเป็นเจ้าของของเช็คใน Transaction ต่าง ๆ ที่ไม่ใช่ P2PKH อยู่อีก หัวข้อนี้เราจะพามาเล่าให้ฟังตัวนึง

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

ดังนั้นวิธีการยืนยันเลยไม่ได้มีแค่ P2PKH ครับ อีกวิธีนึงที่ประกาศใช้เป็นมาตรฐานแล้วคือ Pay to Script Hash (P2SH)

P2SH เกิดจากความคิดว่าถ้าเราต้องการจะระบุเงื่อนไขบางอย่างที่คนรับเงินเท่านั้นที่รู้ มิฉะนั้นถึงมี Private Key ก็ไม่สามารถใช้เงินก้อนนั้นได้ เราจะทำยังไง?

เงื่อนไขที่ว่าก็เช่น ต้องมีรหัสลับใส่เข้าไปด้วยตอนยืนยันความเป็นเจ้าของ มิฉะนั้นจะไม่สามารถสร้าง scriptSig ที่ถูกต้องได้เลย ... อืม น่าสนใจนะ ว่าแต่มันต้องทำยังไงนะ

ถ้าเป็น P2PKH นี่ทำไม่ได้เลย เพราะว่าทุกอย่างมันตรงไปตรงมาหมด ก็คือ scriptPubKey ถูกสร้างมาจาก Public Key Hash ของ Flow นี้

Private Key ==> Public Key ==>
Public Key Hash ==> Bitcoin Address

และเจ้า scriptSig ก็ถูกสร้างมาจาก Private Key แค่นั้น ดังนั้นถ้ามี Private Key ก็จบเห่ เฮ้ เฮ เฮ เฮ

ซึ่งนี่ก็เป็นจุดที่หลายคนกังวล การที่ทุกอย่างอิงกับ Private Key อย่างเดียวมันเสียวไป ต้องหาทางเพิ่มเงื่อนไข ทางผู้พัฒนาเลยเกิดความคิด เออ ไหน ๆ ก็ไหน ๆ เจ้า scriptSig มันก็ใส่โค้ดลงไปได้เนอะ พวก OP_ ทั้งหลายเนี่ย ดังนั้นเลยให้คนสามารถเขียน Script เฉพาะฝังไปกับ scriptSig เลย ! และเราจะเรียกสิ่งนี้ว่า Redeem Script ครับ

โดย Redeem Script จะถูกสร้างเป็น Script แบบเต็ม ๆ เลยโดยมี Public Key เป็นส่วนหนึ่งของชุดคำสั่ง เช่น

<SomePassword> OP_SHA256 "5c26ca3052b2f52fcf706373113ca81fa98131fd62028145c9ad28490d93dec5" OP_EQUALVERIFY <PubKey> OP_CHECKSIG

ยังไม่ต้องสนใจความหมายของคำสั่งพวกนี้ ไว้ไปดูด้านล่างทีเดียว แค่อยากให้เห็นว่า Public Key นั้นเป็นส่วนหนึ่งของ Redeem Script นะ ดังนั้น Flow ของการสร้าง Public Key Hash จึงเปลี่ยนไปเป็นแบบนี้

Private Key ==> Public Key ==> Redeem Script ==>
Redeem Script Hash ==> P2SH Address

จากเดิมเป็น Public Key Hash ก็จะกลายเป็นสร้าง Redeem Script Hash ขึ้นมาแทน และแน่นอน Address จึงเปลี่ยนไป ไม่ใช่ Bitcoin Address ที่ขึ้นต้นด้วยเลข 1 อีกต่อไป แต่จะกลายเป็น P2SH Address ที่ขึ้นต้นด้วยเลข 3 เช่น 3P14159f73E4gFr7JterCCQh9QjiTjiZrG ครับ เวลาจะให้คนอื่นโอนก็ส่งเจ้า P2SH Address ตัวนี้ไปให้คนโอนได้เลย

โดย P2SH จะมีรูปแบบของ scriptPubKey และ scriptSig ดังนี้

scriptPubKey: OP_HASH160 <Hash160(redeemScript)> OP_EQUAL
scriptSig: <sig> [sig] [sig...] <redeemScript>

ก็จะเห็นว่าทั้งฝั่งคนโอนและคนรับมีการเปลี่ยนแปลงของโค้ดส่วนสร้าง scriptPubKey และ scriptSig ด้วย เอาฝั่งคนโอนก่อนละกัน โฟกัสไปที่ scriptPubKey ครับ

scriptPubKey: OP_HASH160 <Hash160(redeemScript)> OP_EQUAL

สำหรับ Hash160(redeemScript) ก็ไม่ใช่อะไร มันก็คือ P2SH Address นั่นเอง เหมือนของกรณี P2PKH เลย ดังนั้นตรงนี้ค่อนข้างเหมือนเดิม ถอดรหัสออกมา เช่น หาก P2SH Address มีค่า 3P14159f73E4gFr7JterCCQh9QjiTjiZrG ก็จะได้ Hash160<redeemScript> เป็น

e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a

จากนั้นประกอบร่างด้วยวิธีเดิม จะได้มาเป็น

a914e9c3dd0c07aac76179ebc76a6c78d4d67c6c160a87

และนี่คือ scriptPubKey ที่เอาไปใช้งานได้แล้วครับ ค่อนข้างคล้ายเดิมแต่เปลี่ยนรูปแบบ OP ไปเล็กน้อย

เพื่อยืนยันความถูกต้อง scriptPubKey ด้านบนมี Transaction จริง อยู่นะ ลองไปจิ้มดูได้ครับ จะเห็นว่า P2SH Address และ scriptPubKey ตรงกับที่เราคำนวณออกมาทุกประการ

ซึ่งคนโอนก็ไม่รู้หรอกนะว่าเจ้า Redeem Script หน้าตาเป็นยังไง แต่ใน scriptPubKey ก็มีค่า Hash ของ Redeem Script ใส่ไว้เรียบร้อยแล้ว ดังนั้นคนที่จะเอาเงินก้อนนี้ไปใช้ได้ต้องรู้ Redeem Script ด้วย มิฉะนั้นจะสร้าง scriptSig ที่เข้าคู่กับ scriptPubKey ไม่ได้เลย

ก็อย่างที่บอก คนที่จะปลดล็อคมันได้ก็มีแต่คนที่รู้ redeemScript นี้เท่านั้น (ไม่สามารถแกะจาก scriptPubKey ได้เพราะว่ามันเป็นเพียงแค่ค่า Hash) ซึ่งคนที่รู้ก็มีคนเดียวคือเจ้าของบัญชี ดังนั้นคนที่รับเงินหากต้องการจะใช้เงินก้อนนี้ก็ต้องระบุ redeemScript ที่ตรงกันไว้ใน scriptSig ด้วย มิฉะนั้นจะไม่มีสิทธิ์ใช้เงินก้อนนี้เลย และการสร้าง scriptSig เราจะสร้างโดยใช้รูปแบบนี้กันครับ

scriptSig: <sig> [sig] [sig...] <redeemScript>

เจ้า redeemScript ก็ไม่มีอะไร แทนลงไปตรง ๆ ด้วย Redeem Script ที่ถูกต้องได้เลย (ก็เจ้าของบัญชีต้องรู้อยู่แล้ว) ส่วน Sig ก็ต้องสร้างขึ้นมาให้สอดคล้องกับคำสั่งใน Redeem Script ครับเพื่อให้ทั้งสคริปต์ทั้งก้อนใน scriptSig ทำงานได้สมบูรณ์แบบ ซึ่งสุดท้ายก็จะได้ค่า scriptSig มาพร้อมใช้งาน ยังไงตรงนี้เดี๋ยวมีตัวอย่างให้ดู แต่ก่อนอื่นขอทำทีละขั้นตอนก่อน

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

ขั้นตอนที่ 1: การยืนยันว่า redeemScript นี้ถูก

วิธีที่ใช้ยืนยันคือเอา <redeemScript> ไปต่อท้ายด้วย scriptPubKey เลยได้ออกมาเป็นแบบนี้

<redeemScript> OP_HASH160 <Hash160(redeemScript)> OP_EQUAL

ซึ่งลองมองแล้วน่าจะรันออกว่า redeemScript จะถูกใส่เข้า Stack และโดน Hash160 จากนั้นจะทำการเช็คว่าค่า Hash นี้ตรงกับค่า Hash ที่ระบุไว้ใน scriptPubKey รึเปล่า

หากตรงกันแปลว่า redeemScript ตรงกันและไปต่อได้ ! แต่หากไม่ตรงกัน Transaction นี้ก็จะ Invalid ทันทีครับ คุณไม่ใช่เจ้าของ อย่ามามั่วววว

ขั้นตอนที่ 2: รัน Redeem Script

แต่หากยืนยันขั้นตอนแรกสำเร็จด้วยดี ขั้นตอนต่อไปเราต้องรัน Redeem Script ตามที่ถูกประกาศไว้ใน scriptSig ครับ

<sig> [sig] [sig...] <redeemScript>

การสร้าง scriptSig ตรงนี้ค่อนข้าง Flexible หละ ด้านหน้าสามารถใส่ Sig ได้หลายตัว ขอให้ค่าต่าง ๆ เหล่านั้นสอดคล้องกับคำสั่งใน redeemScript ก็พอ ยกตัวอย่างเช่น สมมติเราเขียน Redeem Script ว่า

<SomePassword> OP_SHA256 "5c26ca3052b2f52fcf706373113ca81fa98131fd62028145c9ad28490d93dec5" OP_EQUALVERIFY <PubKey> OP_CHECKSIG

ส่วน scriptSig คือ

scriptSig: <sig> <redeemScript>

โดย sig คือ Signature ของ <PubKey> ก็จะได้ว่า Script สมบูรณ์คือ

<sig> <SomePassword> OP_SHA256 "5c26ca3052b2f52fcf706373113ca81fa98131fd62028145c9ad28490d93dec5" OP_EQUALVERIFY <PubKey> OP_CHECKSIG

การทำงานก็เป็นตามนี้ สองตัวแรกถูกยัดเข้าไปใน Stack

Stack: <sig> <SomePassword>

คำสั่ง OP_SHA256 จะทำการ Hash SomePassword ด้วย sha256

Stack: <sig> HASH_SHA256<SomePassword>

และตัว 5c26ca30... จะถูกใส่เข้าใน Stack ต่อ

Stack: <sig> HASH_SHA256<SomePassword> 5c26ca30...

คำสั่ง OP_EQUALVERIFY จะทำการเช็คว่าสองค่าบนสุดของ Stack ตรงกันมั้ย ถ้าตรงกันก็ให้ไปต่อ จะเหลือ

Stack: <sig>

และ <PubKey> จะถูกใส่เข้ามา

Stack: <sig> <PubKey>

สุดท้ายด้วยคำสั่ง OP_CHECKSIG จะทดสอบว่า Signature และ PubKey เข้ากันมั้ยด้วยวิธีแบบเดิม เป็นอันเรียบร้อย

จากขั้นตอนด้านบนจะเห็นสิ่งหนึ่งที่น่าสนใจคือ ถ้าเราไม่รู้ว่า SomePassword คืออะไร เราก็ไม่สามารถทำให้สคริปต์ด้านบนรันผ่านได้เลย

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

P2SH ถูกประกาศให้ใช้งานได้เป็นมาตรฐานใน Bitcoin มาสักพักนึงแล้ว ดังนั้น Client ส่วนใหญ่จะสามารถทำงานกับ P2SH Address ได้อย่างไม่มีปัญหาครับ

ตอนนี้ก็เห็นความแตกต่างของ P2SH Address (ขั้นต้นด้วยเลข 3) และ Bitcoin Address (ขึ้นต้นด้วยเลข 1) แล้ว ก็ลองไปไล่ ๆ ดู Transaction ใน Block ต่าง ๆ ดูครับ จะเริ่มมีความสุขเพราะเข้าใจมันมากขึ้น ^_^

ประโยชน์ของ P2SH ยังไม่หมดแค่นี้ มีอีก ๆ ต่อเลยละกัน

ภาคผนวก: Multisig

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

และนี่คือสิ่งที่เรียกว่า Multisig ครับ

คือการใส่เงื่อนไขไปว่าจะต้องมีคนมา Sign ร่วมกันหลายคนนะถึงจะสามารถสร้าง scriptSig ที่ถูกต้องได้

โดย Multisig มักจะใช้จากพื้นฐานของ P2SH ที่สามารถเขียน Redeem Script ฝังลงไปได้ ท่าที่ใช้กันบ่อยคือ m-of-n P2SH Multisig ก็คือต้องมีผู้ Sign อย่างน้อย m ใน n คนถึงจะสามารถสร้าง scriptSig ได้ เช่นถ้าเป็น 2-of-3 ก็จะมี Redeem Script และ scriptSig หน้าตาแบบนี้

Redeem Script: <OP_2> <A pubkey> <B pubkey> <C pubkey> <OP_3> OP_CHECKMULTISIG
scriptSig: OP_0 <A sig> <C sig> <redeemScript>

การระบุ sig จะใส่ไว้ใน scriptSig ตามปกติ แต่จะใส่ตามจำนวนที่ระบุไว้ในค่า m ซึ่งในที่นี้คือ 2 ก็เลยใส่ <A sig> และ <C sig> ลงไป ซึ่งการจะสร้างค่า sig ทั้งสองตัวได้ เราจะต้องมี Private Key สองตัว ซึ่งนี่คือเงื่อนไขที่ว่านั่นเอง อาจจะเป็น Private Key ของผู้เปิดบัญชีร่วมงี้ ต้องได้รับความยินยอมจากสองในสามคนก่อนถึงจะใช้เงินก้อนนี้ได้

ส่วนการระบุ pubkey จะใส่ไว้ใน Redeem Script ตามจำนวนที่ระบุไว้ในค่า n ซึ่งในที่นี้คือ 3 ก็เลยใส่ <A pubkey>, <B pubkey> และ <C pubkey> ลงไปนั่นเอง

จากนั้นเราจะประกบลิสต์ของ pubkey หน้า-หลังด้วยจำนวนของ m และ n ตามลำดับ ดังนั้น OP_2 จึงถูกใส่ไว้ข้างหน้า และ OP_3 ถูกใส่ไว้ข้างหลัง

พอเอา scriptSig และ Redeem Script มารวมกัน ก็จะได้คำสั่งนี้ใน Stack

OP_0 <A sig> <C sig> <OP_2> <A pubkey> <B pubkey> <C pubkey> <OP_3> OP_CHECKMULTISIG

ซึ่งคำสั่ง OP_CHECKMULTISIG จะทำการวิ่งหาว่า sig ทุกตัวมีเข้าคู่กับ pubkey ครบมั้ย ถ้าครบทุกตัวก็ถือว่าผ่านครับ แต่ถ้าไม่ผ่านก็ Invalid เจ้า Transaction นี้ก็ถือคราวต้องร่ำลา ...

เชื่อว่า Multisig นี้น่าจะมีประโยชน์ในหลาย ๆ Use Case แต่ที่มีประโยชน์สำหรับพวกเราเหล่านักพัฒนาเลยก็คือ มันทำให้เรารู้ว่า ด้วย P2SH เราสามารถทำอะไรได้อีกหลายท่าไม่จำกัดเลยแล้วแต่เราจะจินตนาการได้ครับ

เจ๋งดีนะ =)

สรุปจบบล็อก Blockchain สำหรับนักพัฒนา

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

ถามว่าอ่านมาถึงตรงนี้เราเรียนรู้อะไรจากการทำงานของ Bitcoin บ้าง ?

จริง ๆ จุดประสงค์เราไม่ได้ตั้งใจจะให้ท่าน ๆ นั่งทำ Bitcoin Client หรือก็อป Bitcoin มาใช้งาน แต่เราอยากให้ท่านเข้าใจว่า Bitcoin มันมีวิธีคิดแง่ Implementation ยังไง, ออกแบบ Transaction อย่างไร, มีการใช้ Public Key Crytography อย่างไรให้รัดกุม, มีแนวคิดเรื่อง Proof of Work หรือแม้กระทั่ง Subsidy อย่างไร เพื่อที่ว่าเวลาคุณจะต้องทำระบบ Blockchain ขึ้นมาเอง คุณจะได้สามารถออกแบบได้ว่าต้องทำยังไงเพื่อไม่ให้เกิดช่องโหว่ด้าน Security และสามารถชักจูงคนให้เข้ามาร่วมในระบบได้เยอะ ๆ

เพราะถ้าพูดถึงเทคโนโลยี Blockchain แล้ว ก็คงไม่มีตัวอย่างไหนที่ Implementation ดีกว่า Bitcoin อีกแล้วหละ เนื่องจากมันถูกพัฒนามาอย่างต่อเนื่องและมีคนใช้งานเยอะมาก เดินตามหลังผู้ใหญ่หมาไม่กัดน้อออ ศึกษาหมา เอ้ย ศึกษาผู้ใหญ่เอาไว้ จะได้เอามาประยุกต์ใช้เองในอนาคตได้

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

Blockchain มันก็แค่การกระจายการจัดเก็บข้อมูลไปยังทุกเครื่อง นั่นคือแกนของ Blockchain จริง ๆ ที่เหลือการออกแบบ Transaction และกฎเกณฑ์ต่าง ๆ ก็ล้วนขึ้นอยู่กับเราแล้ว ก็ลองคิดดูสิ ถ้าทำระบบที่ไม่เกี่ยวกับการเงินแล้วจะไปลอก Bitcoin มามันก็ไม่ใช่ช่ะ

บล็อกนี้เป็นอีกบล็อกที่เขียนยาวมาก ยอมรับว่าเหนื่อย แต่ก็หวังว่าเนื้อหาจะมีประโยชน์ต่อทุกท่านทั้งตอนนี้และในอนาคตครับ =)

ยังไงใครอยากสนับสนุนก็สามารถบริจาค Bitcoin มาได้ที่ 1Dk9L8FiXXar7Rk2mJzxEZjcBeVFGdh2Jz ...

ล้อเล่นนะ แต่ถ้าส่งมาจริงก็ยินดีรับ แฮ่ ~~~~~

สำหรับซีรี่ส์ Blockchain ยังไม่จบ เดี๋ยวจะมีต่ออีก Block คราวนี้จะเป็นเรื่องของการประยุกต์ระบบที่ไม่ใช่ Bitcoin ละ ไว้คอยติดตามกันได้จ้า

ขอให้ทุกท่านมีความสุข สวัสดีคร้าบ แว้บบบบบบบบบบบบบ

บทความที่เกี่ยวข้อง

Jan 29, 2017, 16:07
18852 views
แอปหรือเว็บมีปัญหา ไม่ต้องใส่ชุดนักศึกษา แค่สมัครมาขอคำปรึกษากับงาน GDE Clinic ฟรี !
Dec 21, 2016, 23:27
120379 views
Blockchain คืออะไร? อธิบายแบบละเอียด แต่เข้าใจง่าย(มั้ง)
0 Comment(s)
Loading