ส่วนไหนของ code bitcoin ที่บอกจำนวน hashrate ที่เข้ามาในระบบ🫸#️⃣🔍

ถาม : Gemini 2.5 Pro

👤 : ส่วนไหนของ code bitcoin ที่บอกจำนวน hashrate ที่เข้ามาในระบบ ?

💬 : ส่วนของโค้ด Bitcoin ที่เกี่ยวข้องกับการปรับค่าความยาก (difficulty) จะเป็นตัวบ่งชี้ถึง hashrate ที่เข้ามาในระบบโดยอ้อมครับ ไม่มีส่วนไหนของโค้ดที่ระบุค่า hashrate ของทั้งระบบไว้โดยตรง แต่ระบบจะคำนวณและปรับเปลี่ยนความยากในการขุดให้เหมาะสมกับพลังการขุดทั้งหมดในเครือข่าย เพื่อให้สามารถค้นพบบล็อกใหม่ได้โดยเฉลี่ยทุกๆ 10 นาที กลไกนี้ทำงานโดยการเปรียบเทียบเวลาที่ใช้ในการค้นพบ 2,016 บล็อกล่าสุดกับเวลามาตรฐานที่ควรจะเป็น (20,160 นาที หรือ 2 สัปดาห์) หากเวลาที่ใช้จริงน้อยกว่า แสดงว่ามีพลังการขุด (hashrate) เข้ามาในระบบมากขึ้น ทำให้ต้องปรับความยาก (difficulty) ให้สูงขึ้น และในทางกลับกัน ส่วนของโค้ดที่เกี่ยวข้อง ส่วนสำคัญของโค้ดที่ควบคุมกลไกนี้อยู่ในไฟล์ pow.cpp ภายในซอร์สโค้ดของ Bitcoin Core โดยฟังก์ชันหลักคือ CalculateNextWorkRequired()

ภายในฟังก์ชันนี้ จะมีการคำนวณ "target" ใหม่ ซึ่งเป็นค่าผกผันของความยาก โดยมีส่วนสำคัญดังนี้:

  • การคำนวณเวลาที่ใช้จริง: โค้ดจะดึงข้อมูลเวลาของบล็อกล่าสุดและบล็อกที่ 2,016 ก่อนหน้ามาลบกัน เพื่อหา nActualTimespan หรือเวลาที่ใช้ไปจริงๆ ในการหา 2,016 บล็อกล่าสุด

  • การจำกัดช่วงการปรับ: เพื่อป้องกันความผันผวนที่รุนแรงเกินไป โค้ดจะจำกัดการเปลี่ยนแปลงของ nActualTimespan ให้อยู่ระหว่าง 1 ใน 4 ถึง 4 เท่าของเวลาเป้าหมาย (2 สัปดาห์)

  • การคำนวณ Target ใหม่: จากนั้นโค้ดจะนำ Target เดิมมาคูณกับ nActualTimespan และหารด้วย nPowTargetTimespan (2 สัปดาห์) เพื่อหาค่า Target ใหม่

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

👤 : หมายถึง mempool เอาข้อมูลมาจากไหน ว่าในระบบทั้งหมดตอนนี้มีค่า hashrate อยู่ที่เท่าไหร่ ?

💬 : Mempool ไม่ได้เป็นแหล่งข้อมูลสำหรับค่า hashrate ของทั้งระบบครับ แต่เป็นเพียงพื้นที่พักสำหรับธุรกรรม (transactions) ที่ยังไม่ได้รับการยืนยันเท่านั้น

พูดง่ายๆ คือ:

  • Mempool (Memory Pool): คือ "ห้องรอ" ของธุรกรรม 📬 เมื่อคุณส่งบิตคอยน์ ธุรกรรมของคุณจะถูกส่งไปที่ Mempool ก่อน เพื่อรอให้นักขุด (miner) ดึงไปใส่ในบล็อกถัดไป ข้อมูลใน Mempool จึงเป็นเรื่องของธุรกรรม เช่น ผู้ส่ง, ผู้รับ, จำนวนเงิน, และค่าธรรมเนียม (fee)

  • Hashrate: คือ พลังการประมวลผลทั้งหมดในเครือข่าย Bitcoin ที่นักขุดใช้ในการแก้สมการเพื่อสร้างบล็อกใหม่ 💻⛏️

แล้วระบบรู้ค่า Hashrate ทั้งหมดได้อย่างไร? คำตอบคือ ระบบไม่ได้ "รู้" ค่า Hashrate ที่แน่นอน แต่ใช้วิธี "ประมาณการ" โดยอาศัยข้อมูล 2 อย่างจากการสร้างบล็อกที่เกิดขึ้นแล้วบน Blockchain ไม่ใช่จาก Mempool:

  • ค่าความยากในการขุด (Mining Difficulty): เป็นตัวเลขที่ระบบ Bitcoin กำหนดไว้เพื่อควบคุมความเร็วในการเจอบล็อกใหม่ให้เฉลี่ยอยู่ที่ 10 นาทีต่อบล็อก

  • เวลาที่ใช้ในการเจอบล็อกจริง (Block Time): ระบบจะดูว่าในช่วง 2,016 บล็อกล่าสุด ใช้เวลาในการขุดไปเท่าไหร่

หลักการทำงาน:

  • ถ้าเจอบล็อกเร็วกว่า 10 นาที: แสดงว่ามีพลังขุด (Hashrate) เข้ามาในระบบเยอะเกินไป ระบบจะปรับ เพิ่ม ค่า Difficulty ในรอบถัดไป

  • ถ้าเจอบล็อกช้ากว่า 10 นาที: แสดงว่ามีพลังขุด (Hashrate) ในระบบน้อยลง ระบบจะปรับ ลด ค่า Difficulty ลง

ดังนั้น เว็บไซต์หรือเครื่องมือต่างๆ ที่แสดงค่า Hashrate ของ Bitcoin จะใช้สูตรคำนวณจากค่า Difficulty ปัจจุบันและเวลาในการเจอบล็อกล่าสุด เพื่อประมาณการพลังการขุดทั้งหมดในเครือข่าย ณ เวลานั้นๆ ครับ

สรุปคือ ข้อมูล Hashrate มาจากการวิเคราะห์ข้อมูลบน Blockchain ที่เกิดขึ้นแล้ว ไม่ได้มาจากข้อมูลธุรกรรมที่รอการยืนยันใน Mempool ครับ

👤 : ขยายภาพการ hash 1 ครั้ง ของธุรกรรมใน bitcoin ให้เห็นภาพหน่อย

💬 : ได้เลยครับ! ลองนึกภาพการทำ Hash 1 ครั้งของธุรกรรมใน Bitcoin ตามลำดับนี้ดูนะครับ

ขั้นตอนที่ 1: เตรียมข้อมูลธุรกรรม (Transaction Data)

สมมติว่าคุณกำลังส่ง Bitcoin ให้เพื่อนของคุณ ข้อมูลธุรกรรมนี้ประกอบด้วย:

• Input(s): ที่อยู่ Bitcoin และจำนวน Bitcoin ที่คุณใช้จ่าย (อ้างอิงจากธุรกรรมก่อนหน้าที่คุณได้รับมา)

• Output(s): ที่อยู่ Bitcoin ของเพื่อนคุณ และจำนวน Bitcoin ที่เพื่อนคุณจะได้รับ รวมถึงที่อยู่ของคุณเองหากมีการ "ทอน" กลับมา และค่าธรรมเนียม (transaction fee)

• Metadata: เช่น ID ของธุรกรรม, เวลา, ลายเซ็นดิจิทัลของคุณที่ยืนยันว่าคุณเป็นเจ้าของ Bitcoin นั้นๆ

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

ขั้นตอนที่ 2: ป้อนข้อมูลเข้าสู่ฟังก์ชัน Hash

ตอนนี้เราจะนำ "กองเอกสาร" หรือข้อมูลธุรกรรมทั้งหมดนี้ ป้อนเข้าสู่ "เครื่องบีบอัด" อันทรงพลังที่เรียกว่า ฟังก์ชัน Hash (ในกรณีของ Bitcoin คือ SHA-256)

ฟังก์ชันนี้จะรับข้อมูลขนาดเท่าไหร่ก็ได้ ไม่ว่าจะเล็กหรือใหญ่ แล้วจะ "บีบอัด" และ "แปลง" มันให้กลายเป็นสายอักขระที่มีความยาวคงที่เสมอ (256 บิต หรือ 64 ตัวอักษรฐานสิบหก)

ลองนึกภาพเครื่องจักรขนาดใหญ่ที่รับข้อมูลเข้ามาอย่างเป็นระเบียบ แล้วส่งมันเข้าสู่กระบวนการที่ซับซ้อนภายใน

ขั้นตอนที่ 3: ผลลัพธ์ของ Hash (Transaction ID)

หลังจากที่ข้อมูลถูกประมวลผลผ่านฟังก์ชัน Hash SHA-256 (ใน Bitcoin จริงๆ จะ Hash สองรอบ: SHA-256(SHA-256(data))) ผลลัพธ์ที่ได้จะเป็นสายอักขระที่ไม่ซ้ำกัน ความยาว 64 ตัวอักษร นี่คือ Transaction ID (TXID) ของธุรกรรมคุณนั่นเอง

ลองจินตนาการว่าผลลัพธ์ที่ออกมาเป็นเหมือน "คริสตัลข้อมูล" ที่มีคุณสมบัติพิเศษ:

• ไม่สามารถย้อนกลับได้: คุณไม่สามารถใช้ TXID นี้เพื่อสร้างข้อมูลธุรกรรมดั้งเดิมกลับมาได้เลย

• เป็นเอกลักษณ์: แม้ข้อมูลธุรกรรมจะเปลี่ยนไปเพียงเล็กน้อย (เช่น เปลี่ยนค่าธรรมเนียมเพียง 0.00000001 BTC) TXID ก็จะเปลี่ยนไปอย่างสิ้นเชิง

• คงที่: หากข้อมูลธุรกรรมยังคงเดิม TXID ที่ได้ก็จะเหมือนเดิมเสมอ

นี่คือภาพของผลลัพธ์ที่เป็น TXID ที่เป็นเหมือน "ลายนิ้วมือดิจิทัล" ของธุรกรรมของคุณครับ

👤 : Miner นำข้อมูลทั้งหมดใน mempool ณ เวลานั้น มา + กับ nonce เพื่อ hash ออกมาให้ใกล้ target ที่สุด ตลอดเวลาใช่ไหม ?

💬 :

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

1. การเลือกธุรกรรม (ไม่ใช่ทั้งหมด) 🧾

Miner จะสอดส่องดูธุรกรรมทั้งหมดที่รออยู่ใน Mempool แล้วจะ เลือก ธุรกรรมที่จะนำมาใส่ในบล็อกของตัวเอง โดยมีหลักเกณฑ์คือ:

  • ค่าธรรมเนียม (Fee) สูงสุด: Miner จะเลือกธุรกรรมที่ให้ค่าธรรมเนียมสูงที่สุดก่อน เพราะนั่นคือรายได้โดยตรงของพวกเขา

  • ขนาดข้อมูล: Miner จะเลือกธุรกรรมมาใส่จนกว่าจะเกือบเต็มขนาดบล็อกที่กำหนดไว้ (Block Size Limit) ดังนั้น Miner จะไม่ได้นำธุรกรรม "ทั้งหมด" ใน Mempool มาใช้ แต่จะเลือกเฉพาะชุดที่ให้ผลตอบแทนดีที่สุดครับ

2. การสร้าง "Merkle Root" 🌳

หลังจากเลือกธุรกรรมทั้งหมดที่จะใส่ในบล็อกได้แล้ว (สมมติว่า 2,000 ธุรกรรม) Miner จะไม่นำข้อมูลดิบของธุรกรรมทั้งหมดมาต่อกัน แต่จะใช้เทคนิคที่เรียกว่า Merkle Tree

  • จับคู่ Hash: นำ Transaction ID (Hash ของแต่ละธุรกรรม) มาจับคู่กันแล้ว Hash รวมกันไปเรื่อยๆ เป็นชั้นๆ

  • ได้ Hash สุดท้าย: ทำแบบนี้ไปจนสุดท้ายจะได้ Hash ค่าเดียว ที่เป็นตัวแทนของธุรกรรมทั้งหมดในบล็อกนั้น ค่านี้เรียกว่า Merkle Root ข้อดีคือ Merkle Root เป็นข้อมูลขนาดเล็กมาก (32 bytes) แต่สามารถเป็น "ลายนิ้วมือ" ที่ใช้ยืนยันได้ว่าธุรกรรมทั้งหมดในบล็อกไม่มีการเปลี่ยนแปลง

3. การสร้าง "Block Header" ⛓️

นี่คือส่วนที่สำคัญที่สุด เพราะเป็นส่วนที่ Miner จะนำไป Hash จริงๆ ไม่ใช่ข้อมูลธุรกรรมทั้งหมด Block Header คือชุดข้อมูลสรุปของบล็อก ประกอบด้วย:

  1. Version: เวอร์ชั่นของซอฟต์แวร์ Bitcoin

  2. Previous Block Hash: Hash ของบล็อกก่อนหน้า (นี่คือสิ่งที่ทำให้เกิด "Chain")

  3. Merkle Root: Hash ที่เป็นตัวแทนธุรกรรมทั้งหมดที่เลือกมา

  4. Timestamp: เวลาที่เริ่มสร้างบล็อก

  5. Difficulty Target (nBits): ค่าความยากที่ระบบกำหนด

  6. Nonce: ตัวเลขที่ Miner จะสุ่มเปลี่ยนไปเรื่อยๆ

4. การวนลูปเพื่อ Hash ⛏️🎯

ตอนนี้แหละครับ คือกระบวนการที่เรียกว่า "การขุด"

  • Miner จะนำข้อมูล Block Header ทั้ง 6 ส่วนนี้มาต่อกัน

  • จากนั้นทำการ Hash (ด้วยอัลกอริทึม SHA-256 สองรอบ)

  • ตรวจสอบผลลัพธ์: ดูว่าค่า Hash ที่ได้ น้อยกว่าหรือเท่ากับ ค่า Target ที่ระบบกำหนดหรือไม่

    • ถ้าไม่: ก็จะเปลี่ยนค่า Nonce (เช่น จาก 1 เป็น 2, 3, 4...) แล้วนำ Block Header ทั้งก้อนไป Hash ใหม่

    • ถ้าใช่: ยินดีด้วย! Miner คนนั้นเจอบล็อกแล้ว! พวกเขาจะทำกระบวนการนี้ซ้ำๆ ด้วยความเร็วหลายล้านล้านครั้งต่อวินาที (Terrahashes/second)

พูดง่ายๆ ก็คือ: Miner ไม่ได้ยุ่งกับข้อมูลธุรกรรมขนาดใหญ่ตลอดเวลา แต่จะสรุปธุรกรรมทั้งหมดให้เหลือแค่ Merkle Root แล้วนำไปใส่ใน Block Header จากนั้นก็แค่ "ทุบ" หรือ Hash Block Header ก้อนเล็กๆ นี้ซ้ำไปซ้ำมา โดยเปลี่ยนแค่ตัวเลข Nonce ไปเรื่อยๆ จนกว่าจะเจอคำตอบที่ถูกต้องครับ

👤 : หมายถึง miner ทั้งหมด คนที่มีเครื่องขุด หรือ pool ที่ทำ ?

💬 :

ทั้ง individual miners (คนที่มีเครื่องขุดเอง) และ mining pools (กลุ่มของนักขุด) ล้วนทำกระบวนการ Hash ที่ว่ามาทั้งหมดครับ แต่มีความแตกต่างใน "การจัดการ" และ "การแบ่งงาน" กันเล็กน้อย

Solo Miner (นักขุดเดี่ยว) 🧑‍💻

นักขุดเดี่ยวคือคนที่มีเครื่องขุดของตัวเองและเชื่อมต่อกับเครือข่าย Bitcoin โดยตรง พวกเขาจะต้องทำทุกอย่างด้วยตัวเองทั้งหมด:

  1. รัน Full Node: ต้องมีสำเนาของ Blockchain ทั้งหมด เพื่อตรวจสอบธุรกรรมและสร้างบล็อกใหม่

  2. เลือกธุรกรรม: เลือกธุรกรรมจาก Mempool ด้วยตัวเอง

  3. สร้าง Block Header: ประกอบ Block Header ขึ้นมาเอง

  4. หา Nonce: ใช้พลังการขุดของเครื่องตัวเองทั้งหมดในการวนลูป Hash เพื่อหา Nonce ที่ถูกต้อง

  5. รับรางวัลเต็มๆ: ถ้าเจอคำตอบก่อนใคร จะได้รางวัลบล็อกทั้งหมด (ทั้ง Block Reward และ Transaction Fees) ไปคนเดียว ข้อเสีย: ในปัจจุบัน Hashrate ของทั้งระบบสูงมาก โอกาสที่นักขุดเดี่ยวจะเจอบล็อกก่อนใครนั้น ต่ำมากอย่างยิ่ง เหมือนกับการพยายามถูกลอตเตอรี่รางวัลที่ 1 คนเดียวทุกงวด

Mining Pool (กลุ่มนักขุด) 🏊‍♂️

Mining Pool คือการที่นักขุดหลายๆ คน นำกำลังการขุดของตัวเองมารวมกัน เพื่อเพิ่มโอกาสในการเจอบล็อก โดยมี "ผู้จัดการ Pool" (Pool Operator) เป็นศูนย์กลาง

  1. ผู้จัดการ Pool ทำหน้าที่หนัก: Pool Operator จะเป็นคนรัน Full Node, เลือกธุรกรรมจาก Mempool, และสร้าง "ต้นแบบ Block Header" ขึ้นมา

  2. กระจายงาน: ผู้จัดการ Pool จะส่งต้นแบบ Block Header นี้ไปให้สมาชิกทุกคนใน Pool แต่จะ กำหนดช่วงของ Nonce ที่แตกต่างกัน ให้แต่ละคนไปหา เช่น

    • Miner A: หา Nonce ตั้งแต่ 0 ถึง 1,000,000

    • Miner B: หา Nonce ตั้งแต่ 1,000,001 ถึง 2,000,000

    • Miner C: หา Nonce ตั้งแต่ 2,000,001 ถึง 3,000,000

  3. สมาชิกลงแรง Hash: สมาชิกแต่ละคน (เครื่องขุดของเรา) มีหน้าที่แค่รับงานมาแล้วใช้พลังขุดของตัวเองหา Nonce ในขอบเขตที่ได้รับมอบหมายเท่านั้น ไม่ต้องยุ่งกับธุรกรรมหรือการสร้างบล็อกเลย

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

สรุปง่ายๆ:

  • Solo Miner: ทำเองทุกขั้นตอน เหมือนทำธุรกิจคนเดียว เสี่ยงสูง แต่ถ้าสำเร็จก็ได้เต็มๆ

  • Mining Pool: เหมือนเป็นพนักงานในบริษัทใหญ่ บริษัท (Pool) หางานมาให้ เรามีหน้าที่ลงแรงทำในส่วนของเรา แล้วรับเงินเดือน (ส่วนแบ่ง) ตามผลงาน มีรายได้ที่มั่นคงกว่า

👤 : ในทาง code แล้ว ตรงไหนที่ต่างกัน ?

💬 :

แน่นอนครับ ในทางโค้ดแล้ว ความแตกต่างระหว่างการขุดเดี่ยว (Solo Mining) กับการขุดในพูล (Pool Mining) นั้นชัดเจนมาก โดยจะต่างกันที่ "โปรโตคอลที่ใช้สื่อสาร" และ "สิ่งที่ส่งกลับไปเมื่อเจอผลลัพธ์"

พูดให้สั้นที่สุดคือ Solo Miner คุยกับ Bitcoin Node ของตัวเองโดยตรงเพื่อสร้างบล็อกทั้งก้อน ในขณะที่ Pool Miner คุยกับ Pool Server เพื่อรับงานชิ้นเล็กๆ และส่งกลับไปแค่ "หลักฐานการทำงาน"

ตารางเปรียบเทียบเชิงเทคนิค (Code Level)

ประเด็น (Aspect)
Solo Miner (ใช้ bitcoind โดยตรง)
Pool Miner (ใช้ Software เช่น CGMiner)

แหล่งที่มาของงาน

Node Bitcoin Core (bitcoind) ของตัวเอง

Server ของ Mining Pool (เช่น stratum.slushpool.com)

โปรโตคอลสื่อสาร

RPC Call ผ่านคำสั่ง getblocktemplate

Stratum Protocol (ผ่าน TCP/IP)

ข้อมูลที่ได้รับมาประมวลผล

ได้รับ JSON Object ขนาดใหญ่ที่มี ข้อมูลธุรกรรมทั้งหมด, previous hash, bits, etc.

ได้รับ JSON Object ขนาดเล็กที่มี Merkle Root ที่ Pool สร้างไว้แล้ว, previous hash, bits, และ extranonce ที่ไม่ซ้ำกัน

สิ่งที่ส่งกลับไป

เมื่อเจอ Hash ที่ถูกต้อง จะส่ง "Block" ทั้งก้อน ที่สมบูรณ์กลับไปหา Node ด้วยคำสั่ง submitblock

เมื่อเจอ Hash ที่ตรงตาม ความยากของ Pool (Share Difficulty) จะส่ง "Share" กลับไปให้ Pool

ความต้องการ Blockchain

ต้องมี Blockchain ทั้งหมด (Full Node) เพื่อตรวจสอบธุรกรรมและสร้าง Template

ไม่จำเป็นต้องมี Blockchain เลย (หน้าที่ของ Pool)

เจาะลึกความแตกต่างใน Code Logic

  1. การรับงาน: RPC getblocktemplate vs. Stratum Protocol

  • Solo Miner (ใช้ getblocktemplate): โค้ดของ Solo Miner จะทำงานในลักษณะ "Pull" คือการร้องขอข้อมูล โลจิกจะเป็นแบบนี้:

    1. เชื่อมต่อกับ bitcoind ของตัวเองผ่าน RPC

    2. ส่งคำสั่ง getblocktemplate

    3. bitcoind จะรวบรวมธุรกรรมจาก Mempool, สร้าง Merkle Tree, และสร้าง Block Template ทั้งหมด แล้วส่งกลับมาเป็น JSON ก้อนใหญ่

    4. โค้ดของ Miner นำข้อมูลนี้มาประกอบเป็น Block Header แล้วเริ่มวนหา Nonce

    5. ถ้ามีบล็อกใหม่เกิดขึ้นในเครือข่าย Miner จะต้องเริ่มกระบวนการนี้ใหม่ทั้งหมด

  • Pool Miner (ใช้ Stratum): โค้ดของ Pool Miner จะทำงานแบบ "Push" คือรอรับข้อมูลจาก Pool โดยตรง มีประสิทธิภาพกว่ามาก:

    1. เชื่อมต่อกับ Pool Server ผ่าน Stratum Protocol

    2. Pool Server (ซึ่งรัน Full Node อยู่แล้ว) จะทำหน้าที่สร้าง Block Template และส่ง "Job" (งาน) มาให้ Miner

    3. "Job" ที่ส่งมาจะประกอบด้วยข้อมูลที่จำเป็นสำหรับสร้าง Block Header แต่ Pool ได้จัดการเรื่องธุรกรรมและ Merkle Root ไว้ให้เรียบร้อยแล้ว และยังกำหนด extranonce มาให้ เพื่อให้แน่ใจว่า Miner แต่ละคนกำลังทำงานที่ไม่ซ้ำซ้อนกัน

    4. เมื่อมีบล็อกใหม่เกิดขึ้น Pool จะส่ง "Job" ใหม่มาให้ทันที ลดเวลาที่เสียไปโดยเปล่าประโยชน์

  1. การส่งงาน: Block vs. Share นี่คือความแตกต่างที่สำคัญที่สุดในตรรกะของโค้ด

  • Solo Miner (ส่ง Block): เป้าหมายของโค้ดคือการหา Hash ที่ ต่ำกว่า Network Target ซึ่งเป็นเรื่องที่ยากมากๆ โค้ดจะวนลูป Hash ไปเรื่อยๆ และจะมีเงื่อนไขแค่ if (hash < network_target)

    • ถ้าเจอ โค้ดจะประกอบ Block ทั้งก้อน (Header + Transactions) แล้วใช้คำสั่ง submitblock ส่งกลับไปที่ bitcoind ของตัวเองเพื่อประกาศไปทั่วเครือข่าย

    • มันคือเหตุการณ์แบบ "ถูกรางวัลใหญ่" หรือ "ไม่ถูกเลย"

  • Pool Miner (ส่ง Share):

Pool จะกำหนดค่าความยากที่ ต่ำกว่า Network Target มากๆ เรียกว่า Share Difficulty

  • เป้าหมายของโค้ดในเครื่องขุดของเราคือการหา Hash ที่ ต่ำกว่า Share Target ซึ่งเจอบ่อยกว่ามาก

  • โค้ดจะมีเงื่อนไข if (hash < share_target)

  • เมื่อเจอ โค้ดจะไม่ได้สร้างบล็อก แต่จะส่งข้อมูลเล็กๆ (เช่น Job ID, Nonce ที่หาเจอ) กลับไปให้ Pool เพื่อเป็น "หลักฐานว่าเราทำงานอยู่" (Proof of Work) สิ่งนี้เรียกว่า Share

  • Pool จะรวบรวม Share จากทุกคนเพื่อคำนวณส่วนแบ่ง และในบรรดา Share จำนวนมหาศาลที่ถูกส่งเข้ามา หากมี Share ใด Share หนึ่งที่โชคดีพอที่จะมีค่าต่ำกว่า Network Target ด้วย Pool ก็จะนำข้อมูลนั้นมาประกอบเป็นบล็อกที่สมบูรณ์และประกาศไปทั่วเครือข่ายในนามของ Pool นั่นเอง

👤 : ระบบ share ใน pool มี code อย่างไร ?

💬 : ระบบ "Share" ใน Pool ไม่มีโค้ดเป็นไฟล์เดี่ยวๆ ที่ชื่อว่า "share.cpp" แต่เป็น ตรรกะ (Logic) ที่ฝังอยู่ในโปรโตคอลการสื่อสารระหว่างเครื่องขุดกับ Pool Server ซึ่งโปรโตคอลที่นิยมที่สุดคือ Stratum Protocol ครับ

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

ตรรกะการทำงานของ Share ในโค้ด

หัวใจของระบบ Share คือการกำหนด "เป้าหมายที่ง่ายกว่า" ให้กับนักขุด โค้ดจะทำงานตามลำดับตรรกะนี้:

  1. Pool กำหนดเป้าหมาย 2 ระดับ 🎯 เมื่อคุณเชื่อมต่อกับ Pool, Server ของ Pool จะกำหนดเป้าหมายให้คุณ 2 ค่า:

  • Network Target: เป้าหมายจริงของเครือข่าย Bitcoin ที่จะทำให้ได้บล็อกและรางวัลใหญ่ (ยากมาก)

  • Share Target: เป้าหมายที่ ง่ายกว่า Network Target หลายพันหรือหลายล้านเท่า กำหนดโดย Pool เอง (เจอง่าย) ในทางโค้ด: Share Target จะเป็นตัวเลขที่สูงกว่า Network Target มาก (จำไว้ว่าใน Bitcoin ยิ่ง Target ต่ำ ยิ่งยาก)

  1. Pool ส่ง "งาน" (Job) ให้ Miner 📦 Pool Server จะสร้างต้นแบบ Block Header และส่งมาให้เครื่องขุดของคุณพร้อมกับ Share Target

  2. Miner เริ่ม Hash และตรวจสอบผลลัพธ์ ⛏️ นี่คือส่วนของโค้ดในโปรแกรมขุด (เช่น CGMiner, BFGminer) ที่ทำงานวนลูปตลอดเวลา:

  1. Pool รับ "Share" และตรวจสอบ ✅ เมื่อ Pool Server ได้รับ Share ที่คุณส่งมา มันจะทำหน้าที่ตรวจสอบ:

  2. Share ถูกต้องหรือไม่: Pool จะนำข้อมูลที่คุณส่งมา (Job ID + Nonce) มา Hash ซ้ำอีกครั้งเพื่อดูว่าได้ผลลัพธ์ต่ำกว่า Share Target จริงหรือไม่ (ป้องกันการส่ง Share ปลอม)

  3. บันทึกการมีส่วนร่วม: ถ้า Share ถูกต้อง Pool จะบันทึกในฐานข้อมูลว่า Worker ID ของคุณได้ส่งงานมา 1 Share

  4. ตรวจสอบรางวัลใหญ่: Pool จะเช็คด้วยว่า Share นั้นต่ำกว่า Network Target หรือไม่ ถ้าใช่ Pool ก็คือผู้เจอบล็อกนั้นเอง!

ตัวอย่างข้อมูลที่ส่งหากัน (Stratum Protocol)

สิ่งที่เครื่องขุดส่งกลับไปให้ Pool ไม่ใช่บล็อกทั้งก้อน แต่เป็นข้อมูล JSON เล็กๆ ที่เรียกว่า Submission ซึ่งก็คือ "Share" นั่นเอง:

สรุปคือ: โค้ดของระบบ Share ไม่ได้ซับซ้อน มันเป็นเพียงการเพิ่มเงื่อนไข if (hash < share_target) เข้าไปในลูปการขุด เพื่อสร้าง "จุดเช็คพอยต์" ที่เกิดขึ้นบ่อยๆ สำหรับให้นักขุดใช้ส่งเป็นหลักฐานการทำงานให้ Pool ตรวจสอบและคำนวณส่วนแบ่งได้อย่างยุติธรรมนั่นเองครับ

👤 : สามารถศึกษาเรื่อง pool mining code logic ต่อได้จากที่ไหน ?

💬 : ได้เลยครับ เข้าใจแล้วว่าคุณต้องการเจาะจงไปที่ Code Logic ของระบบ Mining Pool โดยเฉพาะ ไม่ใช่ภาพรวมทั้งหมด นี่คือแหล่งข้อมูลทางเทคนิคเน้นๆ ที่จะพาคุณไปดูโค้ดและตรรกะการทำงานของมันโดยตรงครับ

1. อ่าน "พิมพ์เขียว": Stratum Protocol Specification 📜

นี่คือจุดเริ่มต้นที่สำคัญที่สุด เพราะมันคือ "กฎ" หรือ "ภาษา" ที่เครื่องขุด (Miner) และ Pool Server ใช้คุยกัน การเข้าใจเอกสารนี้จะทำให้คุณรู้ว่าโค้ดต้องเขียนขึ้นมาเพื่อทำอะไร

  • Stratum Mining Protocol (Bitcoin Wiki):

    • ทำไมควรอ่าน: เป็นหน้าสรุปที่เข้าใจง่ายที่สุด อธิบายโครงสร้างของ Message ที่ส่งหากัน เช่น mining.subscribe, mining.authorize, mining.submit (การส่ง Share) และ mining.notify (การส่ง Job ใหม่)

    • ลิงก์: en.bitcoin.it/wiki/Stratum_mining_protocol

  • Stratum V1 Specification (ต้นฉบับ):

    • ทำไมควรอ่าน: นี่คือเอกสารอ้างอิงต้นฉบับ มีรายละเอียดครบถ้วน เหมาะสำหรับเวลาที่ต้องการความแม่นยำสูงสุด

    • ลิงก์: slushpool.com/help/manual/stratum-protocol (แม้จะเป็นของ Slush Pool แต่ก็เป็นมาตรฐานที่ใช้กันทั่วไป)

2. ส่องโค้ดจริง: Open-Source Mining Pool Software 🖥️

วิธีที่ดีที่สุดที่จะเข้าใจ Code Logic คือการอ่านโค้ดของจริงที่ทำงานอยู่ โปรเจกต์เหล่านี้คือซอฟต์แวร์ฝั่ง Server ที่ทำหน้าที่ สร้าง Job, ส่ง Job, รับ Share, และตรวจสอบ Share

  • node-open-mining-portal (NOMP):

    • ทำไมควรดู: เป็นหนึ่งใน Pool Software แบบ Open Source ที่ได้รับความนิยมมากที่สุด เขียนด้วย Node.js ทำให้โค้ดค่อนข้างอ่านง่ายสำหรับคนที่คุ้นเคยกับ JavaScript คุณจะเห็น Logic การจัดการ Worker, การคำนวณความยากของ Share, และการจ่ายรางวัลได้ชัดเจน

    • ลิงก์ GitHub: github.com/zone117x/node-open-mining-portal

  • CKPool:

    • ทำไมควรดู: สำหรับคนที่ต้องการดูการทำงานแบบ High-Performance, CKPool เขียนด้วยภาษา C ซึ่งเน้นประสิทธิภาพสูงสุด คุณจะได้เห็นการจัดการ Connection จำนวนมาก และ Logic การทำงานในระดับที่ใกล้ชิดกับ Hardware มากขึ้น

    • ลิงก์ GitHub: github.com/con-Kolivas/ckpool

  • P2Pool:

    • ทำไมควรดู: นี่คือกรณีศึกษาที่น่าสนใจมาก เพราะเป็น Decentralized Pool (ไม่มีศูนย์กลาง) Logic ของมันจะซับซ้อนกว่า Pool ทั่วไป โดยใช้ Blockchain ของตัวเอง (Sharechain) เพื่อบันทึกการทำงานของนักขุด ทำให้โปร่งใสและไม่มีใครควบคุมได้

    • ลิงก์ GitHub: github.com/p2pool/p2pool

3. ดูอีกฝั่ง: Open-Source Mining Software (Client) ⛏️

เพื่อให้เห็นภาพครบวงจร การดูโค้ดฝั่ง Client ที่ทำหน้าที่ รับ Job และ ส่ง Share กลับไปก็สำคัญไม่แพ้กัน

  • CGMiner:

    • ทำไมควรดู: เป็นโปรแกรมขุดสุดคลาสสิกที่เขียนด้วยภาษา C ลองค้นหาไฟล์ที่เกี่ยวกับ stratum.c หรือ driver-stratum.c ในซอร์สโค้ด คุณจะเห็นฟังก์ชันที่ใช้เชื่อมต่อกับ Pool, รับ Job, วนลูป Hash และส่ง Share กลับไปตามโปรโตโคคอล Stratum ทุกประการ

    • ลิงก์ GitHub: github.com/ckolivas/cgminer

    คำแนะนำ: เริ่มต้นจากการอ่าน Stratum Protocol ให้เข้าใจภาพรวมก่อน จากนั้นเลือกโปรเจกต์ Pool Software ที่คุณถนัดภาษาที่สุด (แนะนำ NOMP สำหรับความง่าย) แล้วไล่ดูโค้ดในส่วนที่เกี่ยวข้องกับการจัดการ Job และ Share ครับ นี่คือวิธีที่ดีที่สุดที่จะเข้าใจ "Pool Mining Code Logic" อย่างลึกซึ้งครับ

👤 : ขั้นตอนไหนใน code ที่ mining scan fee ?

💬 : แน่นอนครับ การ "สแกนค่า Fee" ของ Miner ไม่ใช่ขั้นตอนที่แยกออกมาต่างหาก แต่มันคือส่วนสำคัญของตรรกะในขั้นตอน การสร้าง Block Template (Block Template Creation) ซึ่งเป็นขั้นตอนแรกสุดก่อนที่การ Hash จะเริ่มต้นขึ้น

พูดง่ายๆ คือ Miner จะเลือกธุรกรรมที่ให้ผลตอบแทนสูงสุดใส่ในบล็อกของตัวเอง ก่อน ที่จะเริ่มลงแรงขุดหา Nonce ครับ

The Logic Flow: จาก Mempool สู่ Block Template

นี่คือขั้นตอนที่เกิดขึ้นในโค้ดของซอฟต์แวร์ Node (เช่น Bitcoin Core) เมื่อ Miner ต้องการสร้างบล็อกใหม่:

  1. ดึงธุรกรรมทั้งหมดจาก Mempool 📥

  • ซอฟต์แวร์จะเริ่มต้นด้วยการเข้าถึง Mempool ซึ่งเป็น "ห้องรอ" ของธุรกรรมทั้งหมดที่ยังไม่ได้รับการยืนยัน

  1. จัดลำดับความสำคัญด้วย "Feerate" (ไม่ใช่แค่ Fee) 💰

  • หัวใจสำคัญอยู่ตรงนี้ครับ Miner ไม่ได้ดูแค่ว่าใครให้ค่าธรรมเนียม (Fee) เยอะที่สุด แต่จะดู อัตราค่าธรรมเนียม (Feerate) ซึ่งคำนวณจาก fee / size (หน่วยเป็น satoshis per virtual byte หรือ sats/vB)

  • เหตุผล: ธุรกรรมที่มีขนาดเล็กแต่ให้ Fee สูง จะคุ้มค่าพื้นที่ในบล็อกมากกว่าธุรกรรมขนาดใหญ่ที่ให้ Fee เท่ากัน ดังนั้น Feerate จึงเป็นตัวชี้วัดที่ดีที่สุด

  1. จัดการกับความซับซ้อน: Child-Pays-for-Parent (CPFP) 🧠

  • นี่คือส่วนที่ Logic ในโค้ดจะซับซ้อนขึ้นมาก มันไม่ใช่แค่การเรียงลำดับ Feerate จากสูงไปต่ำง่ายๆ

  • ปัญหา: จะเกิดอะไรขึ้นถ้ามีธุรกรรม A (Parent) ที่ให้ Feerate ต่ำมาก แต่มีธุรกรรม B (Child) ที่ใช้ Output จาก A และให้ Feerate สูงลิ่ว? Miner จะไม่สามารถเลือกแค่ธุรกรรม B ได้ เพราะมันต้องใช้ธุรกรรม A ที่ยังไม่ถูกยืนยันก่อน

  • ทางออก (Code Logic): โค้ดจะใช้อัลกอริทึมที่เรียกว่า Ancestor Set Based Fee Rate โดยจะมองธุรกรรมที่เกี่ยวข้องกันเป็น "กลุ่ม" หรือ "แพ็กเกจ" แล้วคำนวณ Feerate ของทั้งกลุ่ม (total fees of package / total size of package) จากนั้นจึงนำ Feerate ของทั้งกลุ่มมาจัดลำดับความสำคัญ

  1. สร้าง "Candidate Block" ทีละชิ้น 🧱

  • หลังจากจัดลำดับความสำคัญของธุรกรรม (หรือกลุ่มธุรกรรม) แล้ว โค้ดจะเริ่มวนลูปเพื่อสร้างบล็อก:

    • หยิบธุรกรรม (หรือกลุ่ม) ที่มี "Ancestor Feerate" สูงที่สุดมาใส่ก่อน

    • บวกขนาดของธุรกรรมเข้าไปในตัวนับขนาดบล็อก (Block Size/Weight)

    • ตรวจสอบว่าขนาดบล็อกยังไม่เต็ม

    • ทำซ้ำไปเรื่อยๆ จนกว่าบล็อกจะเต็ม หรือไม่มีธุรกรรมที่คุ้มค่าจะใส่แล้ว

แล้วมันอยู่ใน Code ส่วนไหน? C++

สำหรับซอร์สโค้ดของ Bitcoin Core ซึ่งเป็นซอฟต์แวร์อ้างอิงหลัก ตรรกะทั้งหมดนี้จะอยู่ที่:

  • ไฟล์: src/node/miner.cpp

  • ฟังก์ชันหลัก: BlockAssembler::CreateNewBlock()

ภายในฟังก์ชันนี้ จะมีการเรียกใช้ Logic ที่ซับซ้อนจาก CTxMemPool เพื่อวนลูปและเลือกธุรกรรมตามอัลกอริทึมที่อธิบายไว้ข้างต้น เพื่อสร้าง Block Template ที่ทำกำไรได้สูงสุด

Pseudocode (โค้ดจำลอง) ของ Logic นี้จะเป็นประมาณนี้

Last updated