ระบบเงินอิเล็กทรอนิกส์แบบ peer-to-peer ระบบเงินอิเล็กทรอนิกส์แบบ peer-to-peer นั้นจะช่วยให้เราสามารถชำระเงินผ่านทางออนไลน์ได้โดยตรงจากฝ่ายหนึ่งไปยังอีกฝ่ายหนึ่งโดยไม่ต้องผ่านตัวกลางอย่างพวกสถาบันการเงิน โดยใช้ digital signature เป็นส่วนหนึ่งในการแก้ปัญหานี้ แต่มันจะไม่มีประโยชน์ใด ๆ เลยหากยังคงต้องอาศัยตัวกลางที่เชื่อถือได้มาแก้ปัญหา double spending เราขอเสนอวิธีแก้ปัญหา double spending โดยใช้เครือข่ายแบบ peer-to-peer ให้เครือข่ายคอยประทับเวลาธุรกรรมต่าง ๆ ในระบบและนำมาเรียงร้อยกันเป็นเส้นสายของ proof-of-work ที่ใช้ hash เพื่อสร้างธุรกรรมที่ไม่สามารถเปลี่ยนแปลงได้ โดยไม่ต้องทำ proof-of-work ใหม่ โดยให้เส้นสายที่ยาวที่สุดนั้น ไม่เพียงแต่ทำหน้าที่เป็นลำดับของธุรกรรมที่เกิดขึ้นเท่านั้น แต่ยังเป็นสิ่งที่พิสูจน์ได้ว่ามาจากกำลังประมวลผล CPU ที่มากที่สุด และตราบใดที่ nodes ส่วนใหญ่ไม่ได้ร่วมมือกันโจมตีเครือข่ายและยังคงควบคุมกำลังประมวลผลส่วนใหญ่ในระบบไว้ พวกเขาก็จะสร้างเส้นสายที่ยาวที่สุดและสามารถเอาชนะผู้ประสงค์ร้ายที่จะโจมตีระบบได้ ตัวเครือข่ายเองไม่ได้ต้องมีโครงสร้างอะไรที่ซับซ้อน ข้อมูลต่าง ๆ ในเครือข่ายจะถูกกระจายส่งต่อโดยไม่ต้องสนใจว่าผู้รับจะได้รับหรือไม่ และ nodes ต่าง ๆ เองก็สามารถที่จะออกจากเครือข่ายและกลับเข้าร่วมใหม่ได้ตามที่ต้องการ โดยยอมรับเส้น proof-of-work ที่ยาวที่สุด เป็นหลักฐานของสิ่งที่เกิดขึ้นในขณะที่ node นั้น ๆ ไม่ได้อยู่ในเครือข่าย #siamstr /ปล. ถ้าใครอ่านแล้วคุ้นก็ใช่ครับ white paper นั้นแหละ ผมเชื่อว่าหลาย ๆ คนน่าจะยังไม่เคยมีโอกาสได้อ่าน (9 หน้ามันก็ยาวอะเนอะ) เลยคิดว่าจะหั่นออกมาทีละส่วน เผื่อใครตามอ่านทุกวันสักสองอาทิตย์ก็เหมือนอ่าน white paper จบ/
มาสร้าง emoji ของเราบน nostr กันเถอะ!! ครั้งนี้จะเป็นการสร้าง emoji list ผ่านทาง nostrudel เนื่องจากเป็น client ที่เป็นที่นิยมและคิดว่าหลาย ๆ คนน่าจะเคยใช้งานกันมาบ้างแล้ว 1. ให้ไปที่ส่วนของ other stuff จากนั้นเลือก more แล้วเราจะเจอหน้าตาประมาณนี้ (รูปที่ 1) image 2. กดเข้าไปในหัวข้อ emoji จากนั้นเลือก create new pack บนมุมบนขวา (รูปที่ 2) image 3. หลังใส่ชื่อเรียบร้อยเราจะเข้าสู่หน้านี้ (รูปที่ 3) image 4. เมื่อเรากด edit ที่มุมบนขวาเราก็จะได้ช่องที่ใส่ชื่อของอิโมจิตัวนั้น ๆ และช่องใส่ url ของรูปภาพหรือ gif มา (รูปที่ 4) image 5. หลังใส่รายละเอียดแล้วให้เรากด add และทำวนไปเรื่อย ๆ จนกว่าจะพอใจ หลังจากนั้นให้เรากด save และทำการ sign ธุรกรรมนั้นก็เป็นอันเสร็จสิ้น เพียงเท่านี้เราก็จะมีอิโมจิของเราที่ไม่เหมือนใครเอาไว้ใช้แล้ว
Emoji บน Nostr บน nostr นั้นการกด reaction (kind 7) ในแต่ละโพสต์นั้นค่อนข้างแตกต่างกับโซเชียลมีเดียอื่น ๆ เป็นอย่างมากเนื่องจากผู้ใช้ทุกคนสามารถที่จะออกแบบและเลือกใช้อิโมจิอะไรก็ได้ที่ตัวผู้ใช้นั้น ๆ ต้องการ โดย emoji จะถูกเก็บอยู่ในลักษณะของ list (NIP-51) เหมือนกับพวก following list, mute list แต่การใช้งานจริง ๆ ทำได้หลากหลายมากกว่านั้น เช่นการจับลง kind 0 หรือ kind 1 ก็สามารถทำได้เช่นกัน ทีนี้เรามาลองดูโครงสร้าง event ของ list emoji กันดีกว่า { "id": "c25122084feb5b70c4c141c515e91dfb6a65c494dae2baf091839ff88a4cc0c3", "pubkey": "66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64", "created_at": 1710736175, "kind": 30030, "tags": [ [ "d", "ชื่อเซตอิโมจิ"], ["emoji","ชื่อสั้น ๆ ","httpรูปหรือ gif"], [ "emoji","ชื่อสั้น ๆ ""httpรูปหรือ gif"], ["emoji","ชื่อสั้น ๆ ","httpรูปหรือ gif"], [ "emoji","ชื่อสั้น ๆ ""httpรูปหรือ gif"], "content": "", "sig": "c4fb0626619fc0881d859570d0d00d72f7a429aca53a322768a6a0c69ddb00e44a87b65bf75a07eb7647407b78803f76720e22eed0724d554470d30371ab1173" } อย่างที่เห็นว่าจุดแตกต่างของ event ที่ทำให้ client ต่าง ๆ รู้ว่ามันคืออีโมจิคือ tag "d"(identifier) และ "emoji" และต้องมีโครงสร้างดังนี้ ["emoji", <shortcode>, <image-url>] เมื่อทำการเผยแพร่ event ในลักษณะนี้แล้วเราก็จะได้ list ของอิโมจิออกมาแบบนี้ View Event → ส่วนถ้าเราต้องการนำ emoji ที่เราสร้างไปใส่ในหน้าโปรไฟล์หรือเวลาเราโพสต์เราต้องทำอย่างไร ? โปรไฟล์(kind 0) { "kind": 0, "content": "{\"name\":\"Alex Gleason :soapbox:\"}", "tags": [ ["emoji", "soapbox", "http s://gleasonator.com/emoji/Gleasonator/soapbox.png"] ], "pubkey": "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6", "created_at": 1682790000 } ใน part ของโปรไฟล์นั้นเพียงแค่เราเพิ่ม shortcode ลงไปในจุดที่เราต้องการใส่และทำการเพิ่ม emoji ใน tag ก็สามารถใช้ได้แล้ว และในทำนองเดียวกันสำหรับการโพสต์ (kind 1) { "kind": 1, "content": "Hello :gleasonator: 😂 :ablobcatrainbow: :disputed: yolo", "tags": [ ["emoji", "ablobcatrainbow", "https: //gleasonator.com/emoji/blobcat/ablobcatrainbow.png"], ["emoji", "disputed", "https: //gleasonator.com/emoji/Fun/disputed.png"], ["emoji", "gleasonator", "https: //gleasonator.com/emoji/Gleasonator/gleasonator.png"] ], "pubkey": "79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6", "created_at": 1682630000 } และประเภทสุดท้ายของการใช้ emoji บน nostr และหน้าจะเป็นประเภทที่หลาย ๆ คนใช้กันมากที่สุดอย่างการกด reaction ด้วย emoji จะมี event หน้าตาประมาณนี้ { "kind": 7, "content": ":soapbox:", "tags": [ ["emoji", "soapbox", "https ://gleasonator.com/emoji/Gleasonator/soapbox.png"] ], ...other fields } ทั้งหมดนี้คือวิธีการใช้อิโมจิต่าง ๆ บน nostr ซึ่งจัดเป็นอีกฟังก์ชั่นที่น่าสนใจมาก ๆ ในการเพิ่มสีสันให้สังคม nostr โดยในปัจจุบันมีหลาย ๆ client ได้รองรับการใช้ custom emoji เหล่านี้แล้วส่วนวิธีการสร้างแบบง่าย ๆ โดยที่ไม่ต้องสนใจสิ่งที่กล่าวมาข้างต้นนั้นสามารถทำได้บน emojito.meme หรือ Nostrudel ได้เลย #siamstr
Bitcoin node บิตคอยน์โหนด หรือก็คือเหล่าบรรดาคุณป้าข้างบ้านที่มีปัญญาในการจดจำอันเลิศล้ำและคอยบอกต่อเรื่องราวต่าง ๆ ที่เขารับรู้มาให้เราเสมอไม่ว่าจะเรื่องราวของข้างบ้าน ข้างหมู่บ้าน ลูก หลาน เหลน ได้อย่างไม่เหน็ดเหนื่อย โอเคกับมาเข้าเรื่องก่อน บิตคอยน์โหนดคือโปรแกรมที่ทำหน้าที่ในการตรวจสอบธุรกรรม หากถูกต้องตามกฎและระเบียบที่แต่ละโหนดกำหนดไว้ โหนดก็จะส่งธุรกรรมและบล๊อกที่ได้รับนั้นไปยังโหนดอื่น ๆ และเก็บสำรองข้อมูลเหล่านั้นไว้เพื่ออ้างอิงในอนาคตด้วย แล้วมันทำงานยังไง ? เมื่อธุรกรรมใหม่ถูกสร้างและส่งต่อในเครือข่าย, บิตคอยน์โหนดจะรับธุรกรรมเหล่านั้นและทำการตรวจสอบตามกฎที่โหนดนั้น ๆ เลือก เช่น ตรวจสอบลายเซ็นดิจิทัลและตรวจสอบ unspent transaction outputs (UTXOs) โดยโหนดจะใช้ BIP ต่าง ๆ เป็นตัวช่วยในการตรวจสอบ เช่น BIP-66 เพื่อการตรวจสอบ digital signature หลังจากการตรวจสอบความถูกต้องของธุรกรรม, บิตคอยน์จะรวมธุรกรรมที่ตรวจสอบแล้วเหล่านี้เข้าไปใน mempool ซึ่งเป็นพื้นที่เก็บข้อมูลของธุรกรรมที่รอการบรรจุลงในบล็อกถัดไป โหนดจะคอยตรวจสอบบล็อกใหม่ที่เผยแพร่จาก miner ซึ่งจะมีการยืนยันบล็อกใหม่เหล่านี้โดยการตรวจสอบลำดับของบล็อกและการตรวจสอบปัญหาต่าง ๆ เช่น มี double-spending มั้ย, มีธุรกรรมที่ out มากกว่า in มั้ย เมื่อโหนดยืนยันบล็อกใหม่แล้ว, บล็อกดังกล่าวจะถูกเพิ่มลงใน blockchain และโหนดจะเผยแพร่ข้อมูลบล็อกใหม่ไปยังโหนดอื่น ๆ ในเครือข่าย เพื่อให้ข้อมูลนี้ถูกกระจายออกไปทั่วเครือข่าย #siamstr
Lightning Zaps การ zap บน nostr ก็เป็นอีเว้นประเภทหนึ่ง ๆ โดยการใน zap แต่ละครั้งจะประกอบไปด้วย 2 อีเว้นก็คือ zap request (9734) และ zap receipt (9735) โดย flow ในการทำงานของการ zap มีดังนี้ 1. client จะทำการอ่าน LNurl หรือ LNaddress จาก profile ของคนที่เราจะ zap และทำการส่ง request ไปยัง LNaddr server นั้น ๆ เมื่อ server ตอบกลับมาก็จะเช็คพารามิเตอร์สองตัวนั้นคือ allowsNostr(True or False) และ nostrPubkey(ตรงกับ npub ของโปรไฟล์ที่เราจะ zap มั้ย) ตามลำดับ ถ้าถูกต้องจะทำการการอ่านพารามิเตอร์ callback(ส่งเงินไป address ไหน), minSendable(ยอดขั้นต่ำ), และ maxSendable(ยอดสูงสุด) กระบวนการทั้งหมดของข้อนี้คือ zap request 2. เมื่อเราทำการจ่าย invoice เรียบร้อย จะมีการสร้าง zap receipt และส่งไปยัง relay ต่าง ๆ โดย event ของทั้สองประดภทมีลักษณะดังนี้ zap request (9734) { "kind": 9734, "content": "Zap!", "tags": [ ["relays", "รีเลย์หนึ่ง", "รีเลย์สอง"], ["amount", "จำนวนที่เราอยาก zap"], ["lnurl", "lnurl ของคนรับ"], ["p", "pubkey คนรับในรูป hex"], ["e", "event id ที่เราจะ zap"] ], "pubkey": "pubkeyคนส่ง", "created_at": เวลา, "id": " ID ของอีเว้นนี้", "sig": " Digital sigature ของธุรกรรมนี้" } zap receipt (9735) { "id": "ID ของอีเว้นนี้", "pubkey": "pubkey ของคนส่ง", "created_at": เวลาที่สร้าง, "kind": 9735, "tags": [ ["p", "pubkeyคนส่งในรูป hex"], ["e", "event id ที่มีคนมา zap"], ["bolt11", "Ln invoice"], ["description", " zap request ทั้งอีเว้น"], ["preimage", "preimage ของ invoice"] ], "content": "", "sig": "Digital signatureของคนส่ง" } #siamstr
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
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
Merkle Tree Merkle Tree เป็น hash-based data structure เหมือนกับ binary tree แต่แตกต่างกันตรงที่ leaf node จะทำการเก็บเพียงแค่ค่า hash ของข้อมูลธุรกรรม ส่วน node ที่ไม่ใช่ leaf node จะเก็บค่าจากการ hash ที่ได้จาก children node หากจะให้เห็นภาพมากขึ้นลองมาดูตัวอย่างตามนี้กันครับ สมมุติให้มี transaction ทั้งหมด 4 transaction: t1, t2, t3, t4 ก็แปลว่า hash ของทั้ง 4 transaction ก็จะเป็น leaf node ดังนี้ H(1), H(2), H(3), H(4) และเนื่องจาก 1 node จะมี 2 children แปลว่า ก็จำเป็นต้องมี 2 node ที่เก็บ hash ของ H(1), H(2), H(3), H(4) ดังนั้นในชั้นที่ 2 ของ tree แต่ละ node จะต้องเก็บข้อมูลเป็น H(H(1)+H(2)), และ H(H(3)+H(4)) ตามลำดับ และดังที่กล่าวไว้ข้างต้น เนื่องจาก 1 node จะมี 2 children แปลว่า ก็จำเป็นต้องมี 1 node ที่เก็บค่า H(H(H(1)+H(2)) + H(H(3)+H(4))) ดังรูปที่แสดงข้างล่างนี้ image เมื่อเราใช้ Merkle Tree มาช่วยจัดการการตรวจสอบธุรกรรมบนบิตคอยน์ ทำให้เราไม่จำเป็นต้องตรวจสอบทุกธุรกรรมในบล๊อก เนื่องจากเราสามารถเช็คเพียงแค่ root hash ว่าตรงกับคนอื่นมั้ย ถ้าตรงก็แปลว่าข้อมูลที่เรารับมาถูกต้อง ในทางกลับกันหากไม่ตรงเราสามารถไล่เช็คตามลำดับของ tree เพื่อตามหาธุรกรรมเจ้าปัญหาได้ง่ายกว่าการไล่เช็คทั้งหมด การนำ merkle tree มาใช้ช่วยให้ การตรวจสอบบล๊อกนั้นทำได้ง่ายขึ้นและใช้พื้นที่ในการเก็บข้อมูลน้อยลง #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