Bitcoin Transaction Structure
ธุรกรรมของบิตคอยน์คือสิ่งที่เกิดขึ้นทุกครั้งที่เราทำการส่งบิตคอยน์ ไม่ว่าจะส่งไปให้คนอื่น หรือแค่ทำสังคายนา utxo ของตัวเองก็ตาม ถ้าให้ว่ากันง่าย ๆ จริง ๆ แล้ว ธุรกรรมของบิตคอยน์ก็แค่ชุดข้อมูลจำนวนหนึ่งที่เอาไว้แค่ล๊อคบิตคอยน์และปลดล๊อคบิตคอยน์ โดยในธุรกรรมจะแบ่งส่วนหลัก ๆ 2 part คือ ขาเข้า(input): เลือกบิตคอยน์ที่เราต้องการปลดล๊อค, ขาออก(output): เอาบิตคอยน์จาก input ไปล๊อคไว้ที่ไหนต่อ และแน่นอนว่าในแต่ละธุรกรรมนั้นจำนวน input และ output นั้นสามารถมีได้มากกว่า 1
โอเคทีนี้เรามาลองดูตัวอย่าง transaction กัน
(ตัวอย่างจาก 1de09872f8726ab057e8b116faf55d0e502acbe8ff94b8025a40105a85218140 // Height 114,932)
tx data: 0100000001c3756a5279ed61735f5ab085f6e10b3f36423020cd4746876dd353ec610cf52c000000008b4830450221008c5730e8dd9509275ab6b8172c9dcfb74b98c855b328cce8b539701755875a53022055caafcff30d19e5fa28b671a37f00704ef8daac0ef06ba35696650850b820bb01410456ee2d5b710bce0e7ce5fd15c47c4021495ad9109a544ffcf7ecd2b049fe98f168ba973c161fa3cdffb1df4d0f208a576a45dea6cbc2b20a48cfc0a588a5b2afffffffff020014df200f0000001976a914ead1471151871931cfe3ed41beb99662f4248d1288ac40420f00000000001976a9146abb64c4751ede732ba3a584de223dbd8989531288ac00000000
ทีนี้เรามาลองชำแหละธุรกรรมนี้กัน ในธุรกรรมนี้มีส่วนประกอบดังนี้: version, input count, input data, output count, output data, และ time lock ดูข้อความด้านล่างนี้ประกอบเอานะครับ
version(4 byte): 01000000
input count: 01 แปลว่าธุรกรรมนี้มี 1 input
input data: ในส่วนนี้แบ่งเป็น 5 ส่วนของแต่ละ input ดังนี้
TXID(32 byte):c3756a5279ed61735f5ab085f6e10b3f36423020cd4746876dd353ec610cf52c
VOUT(4 byte):00000000
ScriptSig Size:8b
ScriptSig:4830450221008c5730e8dd9509275ab6b8172c9dcfb74b98c855b328cce8b539701755875a53022055caafcff30d19e5fa28b671a37f00704ef8daac0ef06ba35696650850b820bb01410456ee2d5b710bce0e7ce5fd15c47c4021495ad9109a544ffcf7ecd2b049fe98f168ba973c161fa3cdffb1df4d0f208a576a45dea6cbc2b20a48cfc0a588a5b2af
* ตรงนี้มันคือ OP_PUSHBYTES_72 กับ OP_PUSHBYTES_65 ไว้เขียนวันหลังนะครับ
sequence(4 byte):ffffffff ส่วนนี้คือตัวกำหนดพวก lock time หรือ RBF (ffffffff คือปกติ ,fdffffff คือ RBF ส่วนพวก timelockจะเริ่มจาก 00000000 และเปลี่ยนลำดับที่ 2 ตามจำนวน block ที่ต้องการเช่น 3 block ก็ 03000000)
input count:02 ธุรกรรมนี้มี 2 output
input data: ในส่วนนี้แบ่งเป็น 3 ส่วนของแต่ละ output ดังนี้
output 1
amount(Little Endian 8 Byte): 0014df200f000000 (64,976,000,000 sat) *รวยเกิ้นนน
ScriptPubKey Size: 19
ScriptPubKey: 76a914ead1471151871931cfe3ed41beb99662f4248d1288ac
output 2
amount(Little Endian 8 Byte): 40420f0000000000 (1,000,000 sat)
ScriptPubKey Size: 19
ScriptPubKey: 76a9146abb64c4751ede732ba3a584de223dbd8989531288ac
time lock: 00000000
โดยคร่าว ๆ ก็ประมาณนี้ครับ ตัวอย่างอาจจะเก่าไปหน่อยแล้วเป็น P2PKH ด้วย เลยไม่ได้มีตัวอย่างในส่วนที่ใช้กันบน segwit อย่าง maker, flag, witness ให้แต่เนื่องจากความยาวพอสมควรแล้วผมขอติดไว้ก่อนแล้วกันนะครับ
#siamstr
Learning_BTC&NOSTR
Learning@siamstr.com
npub10yqg...hcl3
สร้างมาเพื่อแชร์เรื่องราวที่ได้ศึกษาจากการเรียนรู้เรื่องของบิตคอยน์และนอสเตอร์ จะพยายามเขียนทุกวันวันละโพสต์เพื่อเป็นการบังคับให้ตัวเองได้ศึกษามันเรื่อย ๆ ทุกวัน ถ้าผิดพลาดตรงไหนรบกวนช่วยแก้ไขกันด้วยนะครับ
Difficulty Adjustment Algorithm
Difficulty Adjustment Algorithm (DAA) เป็นอีกส่วนหนึ่งที่สำคัญในระบบของบิตคอยน์ เนื่องจากมันเป็นตัวควบคุมความยากง่ายในการขุดบิตคอยน์ ซึ่งความยากง่ายนี้เอง จะส่งผลโดยตรงต่อความเร็วในการขุดบล็อกใหม่รวมไปถึงความมั่นคงของเครือข่ายบิตคอยน์ DAA ทำงานโดยการปรับเปลี่ยนค่า hash เป้าหมายโดยจะยากขึ้นหรือง่ายลงตามกำลังขุดในเครือข่าย เพื่อให้เวลาเฉลี่ยในการขุดบล๊อกใหม่นั้นคงที่ ซึ่ง DAA เป็นสิ่งสำคัญมาก เพราะมันช่วยรักษาความมั่นคงของเครือข่ายและป้องกันความผันผวนของกำลังขุด เนื่องจากหากเวลาในการขุดต่อบล๊อกนั้นมากเกินไป อาจทำให้เครือข่ายอ่อนแอ และง่ายต่อการโจมตีในอนาคต โดยในบิตคอยน์นั้นเราใช้ DAA ที่เรียกว่า "Median Time Past" (MTP) โดยมีหลักการดังนี้
เวลาขุดบล็อกนานกว่า 10 นาที: MTP จะเพิ่มค่าเป้าหมาย ทำให้การขุดบล็อกใหม่ยากขึ้น
เวลาขุดบล็อกน้อยกว่า 10 นาที: MTP จะลดค่าเป้าหมาย ทำให้การขุดบล็อกใหม่ง่ายขึ้น
ตามสมการนี้
New Difficulty = Old Difficulty × (Actual Time / Target Time)
โดยมีการกำหนด target time ไว้ที่ 600
แปลว่า New diff มาจากการที่ใช้ old diff คูณกับ เวลาที่ใช้ไปในหน่วยวินาทีหารกับ 600 ถ้าดูจากสมการนี้จะเห็นได้ว่าตัวแปรที่สำคัญในการกำหนดว่าค่าจะเพิ่มหรือลดอยู่ที่ Actual time ซึ่งทำให้มั่นใจได้เลยว่าเวลาเฉลี่ยของบล๊อกของบิตคอยน์จะอยู่ที่ 10 นาที โดยเฉลี่ย
#siamstr
Nostr event
event บน nostr หรือก็คือ โน๊ตหรือข้อมูลต่าง ๆ ที่เราเห็นกันบน nostr ไม่ว่าจะเป็นข้อมูล profile, เนื้อหาบน note, long-form, หรือแม้แต่การไลฟ์ ล้วนแล้วแต่เป็น event ทั้งหมด โดย event จะมีหน้าตาประมาณนี้
{
"id": ,
"pubkey": ,
"created_at": ,
"kind": ,
"tags": [ [...],[...] ],
"content": ,
"sig":
}
id ก็คือ event id ที่มักจะโชว์เวลาทำการโควทบางโน๊ตบน nostr คำนวณโดยการ นำข้อมูลส่วนอื่น ๆ ใน event (pubkey,create_at,kid,tg,content) มา Serialize จากนั้น hash ด้วย sha256
pubkey ก็คือ npubของเราแต่จะอยู่ในรูปของ hex
create_at ก็คือเวลาที่เราสร้างโน๊ต อยู่ในรูปของ unix timestamp ในวินาที
kind ก็คือเลขที่ใช้กำหนดประเภทของ event อยู่ในรูปของ int (0-65,535)
tag ก็คือ # ที่เราใส่ในโพสต์ต่าง ๆ
content ก็คือเนื้อหาที่อยู่บนโน๊ต
sig ก็คือ digital signature ของเรา ใช้เพื่อยืนยันว่า note นี้มาจาก nsec นั้น ๆ ที่เป็นเจ้าของ npub นั้น ๆ จริง ๆ คำนวณด้วยการใช้ ECDSA กับ serialized event data จาก id และ private key ของเรา
อย่างที่เห็นว่าทุกส่วนของ event ถูกเก็บในรูปของ text แล้ว เราสามารถเห็นรูปภาพหรือวิดีโอบน nostr ได้อย่างไร ?
ที่เราสามารถเห็นรูปภาพหรือวิดีโอบน client ต่าง ๆ ของ nostr ได้เนื่องจากการใช้ URL References
ถ้าเอาแบบเข้าใจง่าย ๆ ก็คือสิ่งที่เก็บบน event ของ nostr คือ url ที่ใช้ Markdown-style เพื่อทำ image embedding ขึ้นมา
#siamstr
Elliptical Curve Digital Signature Algorithm
ECDSA เป็นฟังก์ชันการเข้ารหัสแบบอสมมาตร (asymmetric cryptographic function) ซึ่งอยู่บนสมการ 𝑦² = 𝑥³ + 𝑎𝑥 + 𝑏
ซึ่งจุดเด่นของ Elliptic curve คือเมื่อลากเส้นผ่านสองจุดบนเส้นโค้ง จะมีจุดที่สามที่เส้นตัดผ่านเสมอ จึงเหมาะสมที่จะใช้เป็น ฟังก์ชันทางเดียว (เมล็ดกาแฟและผงกาแฟที่ยกตัวอย่างในโพสต์ก่อน) เนื่องจากมันสามารถที่จะสร้างจุดบนเส้นโค้งที่ไม่มีความสัมพัธ์ใด ๆ กับจุดเริ่มต้นของมันหลังจากทำซ้ำหลาย ๆ ครั้ง โดยบิตคอยน์ใช้ secp256k1 ซึ่งมีพารามิเตอร์ดังนี้
1. a และ b บนสมการเป็น 0 และ 7 ตามลำดับ
2. Prime modulo: 2²⁵⁶ - 2³² - 2⁹ - 2⁸ - 2⁷ - 2⁶ - 2⁴ - 1
3. base point p (บาง source ใช้ว่า Generator point) ในเลขฐาน 16: 04 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798 483ADA77 26A3C465 5DA4FBFC 0E1108A8 FD17B448 A6855419 9C47D08F FB10D4B8
4. ลำดับในเลขฐาน 16: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE BAAEDCE6 AF48A03B BFD25E8C D0364141
* สุดท้ายแล้วสมการออกมาแบบนี้ 𝑦² = (𝑥³+7)over (F p)
* ซึ่งตัวเลขเหล่านี้ไม่ได้อุปโหลกขึ้นมามั่ว ๆ แต่เป็นเลขที่ได้มาตรฐานจาก SECG (The Standards for Efficient Cryptography Group)
อย่างที่กล่าวไว้โพสต์ก่อน private key นั้นมาจากการสุ่ม ส่วน public key นั้นมาจากการคำนวณตามสูตร
public key = private key * base point P
ซึ่งเป็นการทำ scalar multiplication และอย่างที่กล่าวไว้ข้างต้น base point P กำหนดโดย secp256k1และเป็นค่าเดียวกันสําหรับทุกคนที่สร้าง public key หมายความว่า private key หนึ่งอันผ่านสมการนี้ยังไงก็จะได้ public key เดิมเสมอ และเนื่องจากลักษณะของ Elliptic curve ที่เป็นฟังก์ชันที่ย้อนกลับไม่ได้ จึงทำให้ public key ไม่สามารถย้อนกลับไปเป็น private key ได้
#siamstr
Digital keys บนบิตคอยน์
บิตคอยน์ใช้ PKE ซึ่งเป็น asymmetric cryptography เพื่อที่จะสร้างคู่กุญแจขึ้นมา นั้นคือ public key และ private key โดยหากมี private key เราสามารถคำนวณเพื่อหา public key ได้ แต่ในทางกลับกันการมี public key เพียงอย่างเดียวนั้นไม่สามารถย้อนกลับไปหา private key ได้ ถ้าจะให้เห็นภาพง่าย ๆ ลองจินตนาการถึง เมล็ดกาแฟกับผงกาแฟ โดยให้ private key เปรียบเสมือน เมล็ดกาแฟและให้ public key เป็นผงกาแฟ เราสามารถนำเมล็ดกาแฟมาบดเพื่อให้ได้ผงกาแฟเสมอ แต่ในทางกลับกันเราไม่สามารถนำผงกาแฟมาประกอบกับเป็นเมล็ดกาแฟได้ แล้วกุญแจทั้งสองสร้างอย่างไร ?
Private key นั้นสร้างโดยการสุ่มตัวเลข ซึ่งเป็นเลขฐาน 16 จำนวน 64 ตำแหน่ง จึงแทบจะเป็นไปไม่ได้เลยที่จะมีคนที่เผลอสร้าง private key แล้วจะออกมาซ้ำกัน เนื่องจาก private key นั้นมีความเป็นไปได้ถึง 16^64 หรือ 2^256 ซึ่งเท่ากับ 115,792,089,237,316,195,423,570,985,008,690,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000 หรือ 115 * 10^75 ความเป็นไปได้ ใครคิดจะ random เพื่อหาบิตคอยน์ก็สู้ ๆ นะครับผมเป็นกำลังใจให้
Public key สร้างโดยการใช้ private key ของเราไปผ่าน ECDSA (Elliptical Curve Digital Signature Algorithm)
แล้วกุญแจทั้งสองในบิตคอยน์นั้นสามารถทำอะไรได้บ้าง
Public key: มีหน้าที่สำคัญ ๆ อยู่สองอย่าง นั้นคือการสร้าง bitcoin address โดยการนำ public key ไป hash, ใช้เพื่อยืนยันธุรกรรมของบิตคอยน์ (ทั้งสองกระบวนการที่กล่าวมานั้นไม่จำเป็นต้องใช้ private key)
Private key: เป็นส่วนสำคัญในการทำธุรกรรมของบิตคอยน์เนื่องจากทุกธุรกรรมบนบิตคอยน์จำเป็นต้องมี digital signature เพื่อยืนยันว่าคุณเป็นเจ้าของบิตคอยน์นั้นจริง ๆ
* ที่สำคัญเลยคือ private คือของบิตคอยน์นั้นคุณควรเก็บไว้ให้ดีอย่าให้ใครรู้ เนื่องจากหากมีบุคคลอื่นรู้ถึง private key ของคุณ วกเขาก็จะสามารถสร้างธุรกรรมบิตคอยน์ด้วย digital signature ของคุณได้ (เขาจะขโมยบิตคอยน์ของคุณได้!!)