<rss
      xmlns:atom="http://www.w3.org/2005/Atom"
      xmlns:media="http://search.yahoo.com/mrss/"
      xmlns:content="http://purl.org/rss/1.0/modules/content/"
      xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
      xmlns:dc="http://purl.org/dc/elements/1.1/"
      version="2.0"
    >
      <channel>
        <title><![CDATA[123🦈ปลาฉลามขึ้นบก]]></title>
        <description><![CDATA[สวัสดีจ้า ทุกท่านที่หลงเข้ามาไม่ว่าจะตั้งใจหรือบังเอิญ แต่ก็หวังว่าจะได้ประโยชน์กับไปไม่มากก็น้อยนะครับ ;)]]></description>
        <link>https://kritta.npub.pro/author/npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e/</link>
        <atom:link href="https://kritta.npub.pro/author/npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e/rss/" rel="self" type="application/rss+xml"/>
        <itunes:new-feed-url>https://kritta.npub.pro/author/npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e/rss/</itunes:new-feed-url>
        <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
        <itunes:subtitle><![CDATA[สวัสดีจ้า ทุกท่านที่หลงเข้ามาไม่ว่าจะตั้งใจหรือบังเอิญ แต่ก็หวังว่าจะได้ประโยชน์กับไปไม่มากก็น้อยนะครับ ;)]]></itunes:subtitle>
        <itunes:type>episodic</itunes:type>
        <itunes:owner>
          <itunes:name><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:name>
          <itunes:email><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:email>
        </itunes:owner>
            
      <pubDate>Thu, 08 May 2025 14:26:23 GMT</pubDate>
      <lastBuildDate>Thu, 08 May 2025 14:26:23 GMT</lastBuildDate>
      
      <itunes:image href="https://image.nostr.build/28545859b808c06c6a03f4119432c684b68c3d3205a4bfdf74b66e2a55b62dac.gif" />
      <image>
        <title><![CDATA[123🦈ปลาฉลามขึ้นบก]]></title>
        <link>https://kritta.npub.pro/author/npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e/</link>
        <url>https://image.nostr.build/28545859b808c06c6a03f4119432c684b68c3d3205a4bfdf74b66e2a55b62dac.gif</url>
      </image>
      <item>
      <title><![CDATA[สรุปประเด็นจาก Bitcoin++ 2025: Mempool, การขุด และอนาคตของ Bitcoin]]></title>
      <description><![CDATA[หลังจากมีเวลาว่างฟัง คือมันเจ๋งนะ ใครสนใจลองฟังดู]]></description>
             <itunes:subtitle><![CDATA[หลังจากมีเวลาว่างฟัง คือมันเจ๋งนะ ใครสนใจลองฟังดู]]></itunes:subtitle>
      <pubDate>Thu, 08 May 2025 14:26:23 GMT</pubDate>
      <link>https://kritta.npub.pro/post/558100f49b869397/</link>
      <comments>https://kritta.npub.pro/post/558100f49b869397/</comments>
      <guid isPermaLink="false">naddr1qqgr2dfcxycrqe35893rsd3exvunwq3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65wvyajum</guid>
      <category></category>
      
        <media:content url="https://image.nostr.build/516ef4ee5a8515bf5253b6939d5791eab7683027f930c229d434292687a60e49.jpg" medium="image"/>
        <enclosure 
          url="https://image.nostr.build/516ef4ee5a8515bf5253b6939d5791eab7683027f930c229d434292687a60e49.jpg" length="0" 
          type="image/jpeg" 
        />
      <noteId>naddr1qqgr2dfcxycrqe35893rsd3exvunwq3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65wvyajum</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<p>งาน Bitcoin++ ประจำปี 2025 ที่จัดขึ้นที่เมืองออสติน รัฐเท็กซัส เป็นการรวมตัวของนักพัฒนา Bitcoin ที่เจาะลึกในประเด็นทางเทคนิค โดยเฉพาะอย่างยิ่งเรื่อง Mempool, Transaction Relay และ Mining Pools หัวข้อเหล่านี้ถูกเน้นย้ำว่าเป็นหัวข้อที่น่าสนใจและเป็นที่ถกเถียงกัน เป้าหมายหลักของงานคือเพื่อให้เหล่านักพัฒนาและผู้สร้างสรรค์ได้แบ่งปันสิ่งที่พวกเขากำลังทำอยู่ เรียนรู้เกี่ยวกับความท้าทายในการนำ Transaction เข้าสู่ Block และการปรับปรุง Bitcoin รวมถึงส่งเสริมการเติบโตของชุมชน Open-Source</p>
<p>งานในปีนี้เป็นครั้งแรกที่มุ่งเน้นไปที่ Mempool และ Transaction Relay โดยเฉพาะ ซึ่งเกี่ยวข้องโดยตรงกับการสร้าง Block Mempool ถูกมองว่าเป็นพื้นที่ส่วนรวม (commons) และเป็นตลาดประมูลที่เสรีและเปิดกว้างที่สุดแห่งหนึ่งของโลก ที่ซึ่งใครก็ตามที่เป็นเจ้าของ Bitcoin สามารถเสนอราคา (ค่าธรรมเนียม) และใครก็ตามที่ขุด Bitcoin ก็สามารถยอมรับราคานั้นและนำ Transaction เข้า Block ได้ แม้ว่ากระบวนการนี้จะมีความท้าทายและบางครั้งก็เป็นที่ถกเถียงกัน แต่ Bitcoin ยังคงทำงานเป็นระบบแบบอนาธิปไตย (anarchic system) ที่การพัฒนาเกิดขึ้นในลักษณะกระจายศูนย์</p>
<h2>ประเด็นร้อน: OP_RETURN และการถกเถียงเรื่อง Data Carrier</h2>
<p>หนึ่งในประเด็นหลักที่ถูกกล่าวถึงและมีการจัดดีเบตแบบ Oxford-style คือเรื่องขีดจำกัดของ Data Carrier ใน OP_RETURN โดยเฉพาะการถกเถียงเรื่องการปลดขีดจำกัดค่าเริ่มต้นใน Bitcoin Core การถกเถียงนี้สะท้อนให้เห็นถึงความตึงเครียดระหว่างกลุ่มที่เรียกว่า <strong>"Monetary Maximalists"</strong> ซึ่งต้องการให้ Bitcoin เป็นเงินที่ดีที่สุด กับกลุ่ม <strong>"Platform Maximalists"</strong> ที่ต้องการให้ Bitcoin สามารถทำสิ่งต่างๆ ที่ไม่เกี่ยวข้องกับเงินได้มากขึ้น เช่น การออก Token บน Bitcoin</p>
<p>ฝ่ายที่สนับสนุนการปลดขีดจำกัดแย้งว่ามันเป็นปัญหาทางเทคนิคที่ไม่มีวิธีที่มีหลักการในการป้องกันอย่างแท้จริงในระดับ Consensus การพยายามใช้ Filter ใน Mempool เพื่อป้องกันนั้นไม่สามารถทำได้อย่างสมบูรณ์ และผู้ใช้สามารถหาวิธีหลีกเลี่ยงได้ การปลดขีดจำกัดอาจช่วยลดการสร้าง UTXO ที่ใช้ไม่ได้ (unspendable UTXOs) ซึ่งเป็นสิ่งที่แย่กว่า OP_RETURN และจะช่วยประหยัดเวลาของนักพัฒนาจากการโต้เถียงในเรื่องเล็กๆ น้อยๆ</p>
<p>ขณะที่ฝ่ายคัดค้านการปลดขีดจำกัดยืนยันว่า Filter ใน Mempool ทำงานได้ผลในการยับยั้งการใช้ OP_RETURN สำหรับข้อมูลที่ไม่ใช่ทางการเงิน และการปลดขีดจำกัดจะเป็นการทำลาย Filter ที่มีอยู่ พวกเขาแย้งว่า Bitcoin ถูกออกแบบมาให้เป็นระบบการเงิน ไม่ใช่ฐานข้อมูลสำหรับเก็บข้อมูลตามอำเภอใจ การอนุญาตให้เก็บข้อมูลที่ไม่ใช่ทางการเงินจำนวนมากจะทำให้ Transaction ของผู้ใช้ทั่วไปมีค่าใช้จ่ายสูงขึ้น และเป็นการ "ขาย Bitcoin ให้กับผู้ที่เสนอราคาสูงสุด" ซึ่งอาจนำไปสู่การบ่อนทำลายโดยผู้ที่ควบคุมระบบการเงินแบบเก่า พวกเขายืนยันว่า Bitcoin ควรเน้นการเป็นเงิน และการเปลี่ยนแปลงที่ไม่จำเป็นซึ่งทำลาย Filter ที่ทำงานอยู่จะทำให้ความไว้วางใจใน Bitcoin Core ลดลง นอกจากนี้ยังมีการพูดถึงทางเลือกในการใช้ Filter ในระดับ Node เช่นที่ implement ใน Bitcoin Knots</p>
<h2>ความรวมศูนย์ในการขุดและการกระจายศูนย์</h2>
<p>ปัญหาความรวมศูนย์ใน Mining Pool เป็นอีกหัวข้อที่มีการหารืออย่างกว้างขวาง โดยเฉพาะเรื่องความหลากหลายของ Block Template เครื่องมืออย่าง stratum.work ถูกสร้างขึ้นมาเพื่อช่วยให้ผู้สังเกตการณ์สามารถเปรียบเทียบ Block Template จาก Pool ต่างๆ ได้ ข้อมูลแสดงให้เห็นว่า Antpool และ Pool ที่เป็น "เพื่อน" (Antpool and friends) รวมถึง Foundry มีส่วนแบ่ง Hash Rate รวมกันค่อนข้างสูง ซึ่งทำให้เกิดความกังวลเกี่ยวกับความรวมศูนย์ ปัญหาดังกล่าวถูกมองว่าเป็นปัญหาเชิงเศรษฐศาสตร์และแรงจูงใจ มากกว่าปัญหาทางเทคนิคล้วนๆ</p>
<p>ทางออกในการกระจายศูนย์การขุดและการสร้าง Block Template ถูกนำเสนอ โดยเฉพาะโปรโตคอล <strong>Datam</strong> ที่พัฒนาโดย Ocean Mining Datam ถูกออกแบบมาเพื่อการขุดแบบกระจายศูนย์โดยเฉพาะ โดย <strong>กำหนดให้ Miner ต้องรัน Node ของตัวเองเพื่อสร้าง Block Template</strong> ซึ่งแตกต่างจาก Stratum V2 ที่ยังคงมีการใช้งานแบบรวมศูนย์อยู่ Datam Gateway ทำหน้าที่เป็นตัวเชื่อมระหว่าง Miner กับ Pool โดยใช้ Stratum V1 แต่ Miner เป็นผู้สร้าง Block Template เอง โปรโตคอล Datam นั้นเรียบง่าย ใช้ภาษา C เพื่อให้มีขนาดเล็กและมีประสิทธิภาพสูง สามารถทำงานบน Raspberry Pi ได้ และมีการเข้ารหัสระหว่าง Pool กับ Gateway การสร้าง Datam ขึ้นมาใหม่จากศูนย์เป็นเพราะไม่มีโปรโตคอลหรือซอฟต์แวร์ Pool เดิมที่ตอบโจทย์การกระจายศูนย์ได้อย่างสมบูรณ์</p>
<h2>การแก้ไข Bug ใน Consensus (Consensus Cleanup)</h2>
<p>มีการนำเสนอ <strong>BIP 54 หรือ Great Consensus Cleanup</strong> ซึ่งเป็นข้อเสนอ Soft Fork เพื่อแก้ไข Bug เล็กน้อยในกฎ Consensus ของ Bitcoin จุดประสงค์ไม่ใช่การเปลี่ยนแปลงคุณค่าหลักของ Bitcoin แต่เป็นการแก้ไข Bug ที่สามารถทำได้ผ่าน Soft Fork Bug เหล่านี้รวมถึงปัญหาที่อาจนำไปสู่การมี Transaction ID (TXID) ของ Coinbase ซ้ำกันในอนาคตสำหรับ Block ที่เกิดขึ้นก่อน BIP 34 การแก้ไขใน BIP 54 เกี่ยวข้องกับการใช้ Time Locking และการกำหนดค่า End Sequence ใน Coinbase Transaction เพื่อป้องกันปัญหานี้ ข้อเสนอนี้ถูกพัฒนาขึ้นโดย Antoine Riard และมีการหารืออย่างละเอียด</p>
<h2>ความปลอดภัยทางควอนตัมในอนาคต</h2>
<p>ประเด็นเรื่องความปลอดภัยทางควอนตัมของ Bitcoin ก็ถูกหยิบยกขึ้นมาพูดคุย แม้จะดูเป็นปัญหาที่ไกลตัว แต่ก็เป็นสิ่งสำคัญที่จะต้องมีแผนรองรับ <strong>BIP 360</strong> ถูกนำเสนอเป็นข้อเสนอ Soft Fork ทางเลือก (Opt-in soft fork) เพื่อเพิ่มความปลอดภัยทางควอนตัมให้กับ Bitcoin ปัญหาหลักคือผู้ใช้จะต้องเปิดเผย Public Key และ Signature เมื่อใช้จ่าย Transaction และคอมพิวเตอร์ควอนตัมอาจสามารถคำนวณ Private Key จาก Public Key ได้ BIP 360 เสนอให้เพิ่มข้อมูล Public Key และ Signature ที่ผ่านการป้องกันควอนตัมเข้าไปใน Transaction โดยรองรับ Taproot อย่างไรก็ตาม Multisig บางประเภท เช่น P2SH หรือ P2WSH อาจให้การป้องกันได้ดีกว่า เนื่องจากผู้โจมตีจะต้องหา Private Key หลายตัว ในขณะที่ Key Path Spend ของ Taproot อาจไม่ช่วยป้องกันปัญหานี้ BIP 360 ยังกำหนดให้มี Public Key ที่ป้องกันควอนตัมเพียงตัวเดียวเพื่อหลีกเลี่ยงความกำกวมของที่อยู่ Taproot</p>
<h2>นวัตกรรมและกรณีใช้งานอื่นๆ</h2>
<p>นอกจากนี้ยังมีการกล่าวถึงโครงการอื่นๆ ที่น่าสนใจ เช่น <strong>Maple AI</strong> ที่มุ่งมั่นสร้าง AI ที่ไม่ใช่แบบรวมศูนย์ และ <strong>Open Secret</strong> ซึ่งเป็น Framework สำหรับนักพัฒนาในการให้ผู้ใช้สามารถ <strong>Self-Custody ข้อมูลของตนเองได้</strong> แนวคิดนี้คล้ายกับการ Self-Custody Bitcoin ใน Wallet โดยมองว่าการถือข้อมูลผู้ใช้เป็นภาระความเสี่ยงสำหรับนักพัฒนา</p>
<p>มีการพูดถึงแนวโน้มที่ผู้เล่นในระบบการเงินแบบเก่าอย่าง Visa และ Stripe กำลังพยายามเข้าสู่พื้นที่ Digital Currency โดยอาจใช้การ Tokenize Credit Card รวมถึงบทบาทที่อาจเกิดขึ้นของ <strong>AI Agents</strong> ซึ่งอาจเริ่มใช้ Bitcoin หรือ Lightning Network ในการชำระเงินในอนาคต มีการคาดการณ์ว่า AI Agents อาจทำธุรกรรมผ่าน Lightning Network ได้ในระดับที่สูงกว่าการใช้งานของมนุษย์อย่างรวดเร็ว โดยมีการพัฒนาโปรโตคอลอย่าง X402 และ Fusats เพื่อรองรับการชำระเงินสำหรับ Agents โดยเปิดโอกาสให้ Agents เลือกใช้สกุลเงินดิจิทัลที่ดีที่สุดในตลาดเสรี</p>
<p>สุดท้าย งาน Bitcoin++ เน้นย้ำถึงความสำคัญของการประชุมและการรวมตัวกันของนักพัฒนาเพื่อหารือ ประสานงาน และแบ่งปันไอเดีย โดยเฉพาะในประเด็นที่ต้องอาศัยความร่วมมือและการแก้ปัญหาที่ซับซ้อน</p>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<p>งาน Bitcoin++ ประจำปี 2025 ที่จัดขึ้นที่เมืองออสติน รัฐเท็กซัส เป็นการรวมตัวของนักพัฒนา Bitcoin ที่เจาะลึกในประเด็นทางเทคนิค โดยเฉพาะอย่างยิ่งเรื่อง Mempool, Transaction Relay และ Mining Pools หัวข้อเหล่านี้ถูกเน้นย้ำว่าเป็นหัวข้อที่น่าสนใจและเป็นที่ถกเถียงกัน เป้าหมายหลักของงานคือเพื่อให้เหล่านักพัฒนาและผู้สร้างสรรค์ได้แบ่งปันสิ่งที่พวกเขากำลังทำอยู่ เรียนรู้เกี่ยวกับความท้าทายในการนำ Transaction เข้าสู่ Block และการปรับปรุง Bitcoin รวมถึงส่งเสริมการเติบโตของชุมชน Open-Source</p>
<p>งานในปีนี้เป็นครั้งแรกที่มุ่งเน้นไปที่ Mempool และ Transaction Relay โดยเฉพาะ ซึ่งเกี่ยวข้องโดยตรงกับการสร้าง Block Mempool ถูกมองว่าเป็นพื้นที่ส่วนรวม (commons) และเป็นตลาดประมูลที่เสรีและเปิดกว้างที่สุดแห่งหนึ่งของโลก ที่ซึ่งใครก็ตามที่เป็นเจ้าของ Bitcoin สามารถเสนอราคา (ค่าธรรมเนียม) และใครก็ตามที่ขุด Bitcoin ก็สามารถยอมรับราคานั้นและนำ Transaction เข้า Block ได้ แม้ว่ากระบวนการนี้จะมีความท้าทายและบางครั้งก็เป็นที่ถกเถียงกัน แต่ Bitcoin ยังคงทำงานเป็นระบบแบบอนาธิปไตย (anarchic system) ที่การพัฒนาเกิดขึ้นในลักษณะกระจายศูนย์</p>
<h2>ประเด็นร้อน: OP_RETURN และการถกเถียงเรื่อง Data Carrier</h2>
<p>หนึ่งในประเด็นหลักที่ถูกกล่าวถึงและมีการจัดดีเบตแบบ Oxford-style คือเรื่องขีดจำกัดของ Data Carrier ใน OP_RETURN โดยเฉพาะการถกเถียงเรื่องการปลดขีดจำกัดค่าเริ่มต้นใน Bitcoin Core การถกเถียงนี้สะท้อนให้เห็นถึงความตึงเครียดระหว่างกลุ่มที่เรียกว่า <strong>"Monetary Maximalists"</strong> ซึ่งต้องการให้ Bitcoin เป็นเงินที่ดีที่สุด กับกลุ่ม <strong>"Platform Maximalists"</strong> ที่ต้องการให้ Bitcoin สามารถทำสิ่งต่างๆ ที่ไม่เกี่ยวข้องกับเงินได้มากขึ้น เช่น การออก Token บน Bitcoin</p>
<p>ฝ่ายที่สนับสนุนการปลดขีดจำกัดแย้งว่ามันเป็นปัญหาทางเทคนิคที่ไม่มีวิธีที่มีหลักการในการป้องกันอย่างแท้จริงในระดับ Consensus การพยายามใช้ Filter ใน Mempool เพื่อป้องกันนั้นไม่สามารถทำได้อย่างสมบูรณ์ และผู้ใช้สามารถหาวิธีหลีกเลี่ยงได้ การปลดขีดจำกัดอาจช่วยลดการสร้าง UTXO ที่ใช้ไม่ได้ (unspendable UTXOs) ซึ่งเป็นสิ่งที่แย่กว่า OP_RETURN และจะช่วยประหยัดเวลาของนักพัฒนาจากการโต้เถียงในเรื่องเล็กๆ น้อยๆ</p>
<p>ขณะที่ฝ่ายคัดค้านการปลดขีดจำกัดยืนยันว่า Filter ใน Mempool ทำงานได้ผลในการยับยั้งการใช้ OP_RETURN สำหรับข้อมูลที่ไม่ใช่ทางการเงิน และการปลดขีดจำกัดจะเป็นการทำลาย Filter ที่มีอยู่ พวกเขาแย้งว่า Bitcoin ถูกออกแบบมาให้เป็นระบบการเงิน ไม่ใช่ฐานข้อมูลสำหรับเก็บข้อมูลตามอำเภอใจ การอนุญาตให้เก็บข้อมูลที่ไม่ใช่ทางการเงินจำนวนมากจะทำให้ Transaction ของผู้ใช้ทั่วไปมีค่าใช้จ่ายสูงขึ้น และเป็นการ "ขาย Bitcoin ให้กับผู้ที่เสนอราคาสูงสุด" ซึ่งอาจนำไปสู่การบ่อนทำลายโดยผู้ที่ควบคุมระบบการเงินแบบเก่า พวกเขายืนยันว่า Bitcoin ควรเน้นการเป็นเงิน และการเปลี่ยนแปลงที่ไม่จำเป็นซึ่งทำลาย Filter ที่ทำงานอยู่จะทำให้ความไว้วางใจใน Bitcoin Core ลดลง นอกจากนี้ยังมีการพูดถึงทางเลือกในการใช้ Filter ในระดับ Node เช่นที่ implement ใน Bitcoin Knots</p>
<h2>ความรวมศูนย์ในการขุดและการกระจายศูนย์</h2>
<p>ปัญหาความรวมศูนย์ใน Mining Pool เป็นอีกหัวข้อที่มีการหารืออย่างกว้างขวาง โดยเฉพาะเรื่องความหลากหลายของ Block Template เครื่องมืออย่าง stratum.work ถูกสร้างขึ้นมาเพื่อช่วยให้ผู้สังเกตการณ์สามารถเปรียบเทียบ Block Template จาก Pool ต่างๆ ได้ ข้อมูลแสดงให้เห็นว่า Antpool และ Pool ที่เป็น "เพื่อน" (Antpool and friends) รวมถึง Foundry มีส่วนแบ่ง Hash Rate รวมกันค่อนข้างสูง ซึ่งทำให้เกิดความกังวลเกี่ยวกับความรวมศูนย์ ปัญหาดังกล่าวถูกมองว่าเป็นปัญหาเชิงเศรษฐศาสตร์และแรงจูงใจ มากกว่าปัญหาทางเทคนิคล้วนๆ</p>
<p>ทางออกในการกระจายศูนย์การขุดและการสร้าง Block Template ถูกนำเสนอ โดยเฉพาะโปรโตคอล <strong>Datam</strong> ที่พัฒนาโดย Ocean Mining Datam ถูกออกแบบมาเพื่อการขุดแบบกระจายศูนย์โดยเฉพาะ โดย <strong>กำหนดให้ Miner ต้องรัน Node ของตัวเองเพื่อสร้าง Block Template</strong> ซึ่งแตกต่างจาก Stratum V2 ที่ยังคงมีการใช้งานแบบรวมศูนย์อยู่ Datam Gateway ทำหน้าที่เป็นตัวเชื่อมระหว่าง Miner กับ Pool โดยใช้ Stratum V1 แต่ Miner เป็นผู้สร้าง Block Template เอง โปรโตคอล Datam นั้นเรียบง่าย ใช้ภาษา C เพื่อให้มีขนาดเล็กและมีประสิทธิภาพสูง สามารถทำงานบน Raspberry Pi ได้ และมีการเข้ารหัสระหว่าง Pool กับ Gateway การสร้าง Datam ขึ้นมาใหม่จากศูนย์เป็นเพราะไม่มีโปรโตคอลหรือซอฟต์แวร์ Pool เดิมที่ตอบโจทย์การกระจายศูนย์ได้อย่างสมบูรณ์</p>
<h2>การแก้ไข Bug ใน Consensus (Consensus Cleanup)</h2>
<p>มีการนำเสนอ <strong>BIP 54 หรือ Great Consensus Cleanup</strong> ซึ่งเป็นข้อเสนอ Soft Fork เพื่อแก้ไข Bug เล็กน้อยในกฎ Consensus ของ Bitcoin จุดประสงค์ไม่ใช่การเปลี่ยนแปลงคุณค่าหลักของ Bitcoin แต่เป็นการแก้ไข Bug ที่สามารถทำได้ผ่าน Soft Fork Bug เหล่านี้รวมถึงปัญหาที่อาจนำไปสู่การมี Transaction ID (TXID) ของ Coinbase ซ้ำกันในอนาคตสำหรับ Block ที่เกิดขึ้นก่อน BIP 34 การแก้ไขใน BIP 54 เกี่ยวข้องกับการใช้ Time Locking และการกำหนดค่า End Sequence ใน Coinbase Transaction เพื่อป้องกันปัญหานี้ ข้อเสนอนี้ถูกพัฒนาขึ้นโดย Antoine Riard และมีการหารืออย่างละเอียด</p>
<h2>ความปลอดภัยทางควอนตัมในอนาคต</h2>
<p>ประเด็นเรื่องความปลอดภัยทางควอนตัมของ Bitcoin ก็ถูกหยิบยกขึ้นมาพูดคุย แม้จะดูเป็นปัญหาที่ไกลตัว แต่ก็เป็นสิ่งสำคัญที่จะต้องมีแผนรองรับ <strong>BIP 360</strong> ถูกนำเสนอเป็นข้อเสนอ Soft Fork ทางเลือก (Opt-in soft fork) เพื่อเพิ่มความปลอดภัยทางควอนตัมให้กับ Bitcoin ปัญหาหลักคือผู้ใช้จะต้องเปิดเผย Public Key และ Signature เมื่อใช้จ่าย Transaction และคอมพิวเตอร์ควอนตัมอาจสามารถคำนวณ Private Key จาก Public Key ได้ BIP 360 เสนอให้เพิ่มข้อมูล Public Key และ Signature ที่ผ่านการป้องกันควอนตัมเข้าไปใน Transaction โดยรองรับ Taproot อย่างไรก็ตาม Multisig บางประเภท เช่น P2SH หรือ P2WSH อาจให้การป้องกันได้ดีกว่า เนื่องจากผู้โจมตีจะต้องหา Private Key หลายตัว ในขณะที่ Key Path Spend ของ Taproot อาจไม่ช่วยป้องกันปัญหานี้ BIP 360 ยังกำหนดให้มี Public Key ที่ป้องกันควอนตัมเพียงตัวเดียวเพื่อหลีกเลี่ยงความกำกวมของที่อยู่ Taproot</p>
<h2>นวัตกรรมและกรณีใช้งานอื่นๆ</h2>
<p>นอกจากนี้ยังมีการกล่าวถึงโครงการอื่นๆ ที่น่าสนใจ เช่น <strong>Maple AI</strong> ที่มุ่งมั่นสร้าง AI ที่ไม่ใช่แบบรวมศูนย์ และ <strong>Open Secret</strong> ซึ่งเป็น Framework สำหรับนักพัฒนาในการให้ผู้ใช้สามารถ <strong>Self-Custody ข้อมูลของตนเองได้</strong> แนวคิดนี้คล้ายกับการ Self-Custody Bitcoin ใน Wallet โดยมองว่าการถือข้อมูลผู้ใช้เป็นภาระความเสี่ยงสำหรับนักพัฒนา</p>
<p>มีการพูดถึงแนวโน้มที่ผู้เล่นในระบบการเงินแบบเก่าอย่าง Visa และ Stripe กำลังพยายามเข้าสู่พื้นที่ Digital Currency โดยอาจใช้การ Tokenize Credit Card รวมถึงบทบาทที่อาจเกิดขึ้นของ <strong>AI Agents</strong> ซึ่งอาจเริ่มใช้ Bitcoin หรือ Lightning Network ในการชำระเงินในอนาคต มีการคาดการณ์ว่า AI Agents อาจทำธุรกรรมผ่าน Lightning Network ได้ในระดับที่สูงกว่าการใช้งานของมนุษย์อย่างรวดเร็ว โดยมีการพัฒนาโปรโตคอลอย่าง X402 และ Fusats เพื่อรองรับการชำระเงินสำหรับ Agents โดยเปิดโอกาสให้ Agents เลือกใช้สกุลเงินดิจิทัลที่ดีที่สุดในตลาดเสรี</p>
<p>สุดท้าย งาน Bitcoin++ เน้นย้ำถึงความสำคัญของการประชุมและการรวมตัวกันของนักพัฒนาเพื่อหารือ ประสานงาน และแบ่งปันไอเดีย โดยเฉพาะในประเด็นที่ต้องอาศัยความร่วมมือและการแก้ปัญหาที่ซับซ้อน</p>
]]></itunes:summary>
      <itunes:image href="https://image.nostr.build/516ef4ee5a8515bf5253b6939d5791eab7683027f930c229d434292687a60e49.jpg"/>
      </item>
      
      <item>
      <title><![CDATA[ห้องทดลองของหลาม #1]]></title>
      <description><![CDATA[]]></description>
             <itunes:subtitle><![CDATA[]]></itunes:subtitle>
      <pubDate>Thu, 02 May 2024 06:49:46 GMT</pubDate>
      <link>https://kritta.npub.pro/post/rbucw9lxpcmxdmymiuxtq/</link>
      <comments>https://kritta.npub.pro/post/rbucw9lxpcmxdmymiuxtq/</comments>
      <guid isPermaLink="false">naddr1qq2hycn4gdmnjmrc2pp567ryf4u566t4tp29zq3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65wptn7f8</guid>
      <category>หลามมันร้าย</category>
      
        <media:content url="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1714632586167-YAKIHONNES3.jpg" medium="image"/>
        <enclosure 
          url="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1714632586167-YAKIHONNES3.jpg" length="0" 
          type="image/jpeg" 
        />
      <noteId>naddr1qq2hycn4gdmnjmrc2pp567ryf4u566t4tp29zq3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65wptn7f8</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<h2>สร้าง Nostr Bot ด้วย Python</h2>
<blockquote>
<p><em>อะแฮ่ม ขอชี้แจงไว้ก่อนว่า ผมเขียนเพื่อให้ตัวเองอ่านเพื่อวันไหนจะกลับมาทำต่อจะได้พอจำได้ว่าตัวเองทำอะไรลงไปบ้าง เพราะงั้นบางส่วนในบทความนี้อาจจะไม่ละเอียด หากลองทำตามแล้วติดตรงไหนอยากสอบถาม ติดต่อมาได้ที่ Nostr Address: <a href="https://nosta.me/nprofile1qy0hwumn8ghj7mn0wd68ytfsxvhxgmmjv9nxzcm5dae8jtn0wfnj7qgcwaehxw309aex2mrp0yhxumm5daeks6fwwa5kutcqypnd7czk9kfe4k5xzfpkfzv5tf8v78tzx34nm9rcm652xw8nyq7xgdzhmy5">kritta@rightshift.to</a> หรือลองค้นเพิ่มเติมใน link ท้ายบทความนะครับ</em></p>
</blockquote>
<p>อย่างที่หลาย ๆ คนน่าจะทราบกันดีอยู่แล้วว่า Nostr เป็น open protocol ที่ใคร ๆ ก็สามารถเข้ามามีส่วนร่วมในการพัฒนาได้ ทำให้มีโปรเจคต่าง ๆ เกิดขึ้นมากมาย โดยบทความในชุดนี้ผมจะหยิบโปรเจคต่าง ๆ ที่น่าสนใจมามาลองเล่น และนำมาเล่าสู่กันฟัง หวังว่าผู้ที่หลงเข้ามาอ่านจะได้ประโยชน์จากสิ่งนี้นะครับ ;)</p>
<p>โดยในวันนี้โปรเจคที่ผมหยิบมาคือ NDK (Nostr development kit) ผมหาไม่เจอว่าใครเป็นคนเริ่มโปรเจค แต่คนที่ดูแล repo นี้หลัก ๆ คือคุณ <a href="https://nosta.me/nprofile1qywhwumn8ghj7mn0wd68ytndw46xjmnewaskcmr9wshxxmmd9uq36amnwvaz7tmjv4kxz7fwd46hg6tw09mkzmrvv46zucm0d5hsqgrgmqgktyvpqzma5slu9rmarlqj24zxdcg3tzrtneamxfhktmzzwg2x3v53">yukibtc</a> เริ่มต้นเหมือนจะเริ่มจาก RUST แต่ตอนนี้เหมือนจะแตกไป swift, java, python เอาจริง ๆ ผมไม่รู้หรอกว่าใครเป็นคนทำภาษาไหนเพราะ contributors เขาเยอะมาก แต่ก็นั่นแหละ ขอบคุณที่สร้างอะไรสนุก ๆ แบบนี้ออกมาให้ได้เล่นนะครับ</p>
<p>โดยอย่างแรกที่เราต้องเริ่มคือการสั่ง pip install ตัว nostr sdk เพื่อใช่งาน สำหรับคนที่ไม่มี python ในเครื่องก็ไปลง python ก่อนด้วยนะ หรือจะใช้ online ผ่าน google colab ลองเล่นดูก่อนก็ได้</p>
<pre><code>pip install pip install nostr-sdk 
</code></pre>
<p>จากนั้นเราก็จะสามารถใช้งาน Nostr_sdk ได้แล้ว!!!<br>โดยการที่เราจะเข้ามาใช้งาน Nostr ได้นั้นเราจำเป็นต้องมี keys เพื่อเข้าสู่ระบบเสียก่อนงั้นเรามาเริ่มจากการสร้าง keys กันก่อน</p>
<pre><code>from nostr_sdk import  Keys
#เพียงคำสั่งนี้คำสั่งเดียวก็ได้ keys แล้วงั้นเหรอ!!
keys = Keys.generate()
#แยก keys ออกเป็น secret key (sk) และ public key (pk) 
sk = keys.secret_key()
pk = keys.public_key()
#ไหน ๆ ขอดู keys หน่อยสิ้
print(f"public key: {pk.to_bech32()}")
print(f"Secret key: {sk.to_bech32()}")
#output:
#public key: npub1wkxaxzmmamc6h8n6ev7yq3y5qmqnyxmu0xmrllcepxup9tktuzrsu646r0
#Secret key: nsec160gefyqkderqlnr545ps4d5th6pex3ducqgcev69z0rstqakkv9scvat97
</code></pre>
<p><em>note ถ้าสร้าง keys เสร็จแล้วเอาไปเก็บไว้ในพวก dot env จะปลอดภัยและสะดวกในการใช้ต่อมากกว่า</em></p>
<p>แล้วหลังจากได้ keys มาแล้วเราจำเป็นต้องกำหนด signer, client และ relay ที่เราจะใช้ในการรับ event ของเรา</p>
<pre><code># กำหนด keys ที่เราพึ่งสร้างให้เป็นตัว sign event
signer = NostrSigner.keys(keys)
# นำเข้า key ที่มีอยู่แล้ว
# app_keys = Keys.parse("nsec......")
# signer = NostrSigner.keys(app_keys)
# หรือใช้ NIP46 signer
# uri = NostrConnectUri.parse("bunker://.. or nostrconnect://..")
# nip46 = Nip46Signer(uri, app_keys, timedelta(seconds=60), None)
# signer = NostrSigner.nip46(nip46)
# กำหนด client ให้ใช้ signer ตัวนี้ (feel like log in)
client = Client(signer)

# เพิ่ม relays ที่จะเก็บ event
client.add_relays(["wss://relay.damus.io", "wss://siamstr.com", "wss://siamstr.com","wss://relay.notoshi.win"])
client.connect()
#ตั้งชื่อให้ account เราสักหน่อยเพื่อเช็คด้วยว่า เราเชื่อมต่อ relay ต่าง ๆ ผ่านมั้ย
client.set_metadata(Metadata().set_name("Testing หลาม ๆ"))
</code></pre>
<p>หลังจากกำหนดทุกอย่างเรียบร้อยแล้ว เรามาลองสร้างโพสต์แรกกันเลยดีกว่า</p>
<pre><code>#tag เพื่อเอาไว้เติมส่วนต่าง ๆ นอกจาก เนื้อหาของโน๊ต เช่นการ mention การใส่ hashtag
# p = mention
# t = hashtag
tag = Tag.parse(["p", "66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64"])
#ใส่เนื้อหาที่เราค้องการโพสต์
builder = EventBuilder.text_note("สวัสดีชาวทุ่ง ", [tag])
ส่ง event ไปให้ relay โลดดดด
client.send_event_builder(builder)
</code></pre>
<p>แล้วนอกจากโพสต์ตระกูล kind:1 แล้วเรายังโพสต์ kind อื่น ๆ ได้ด้วย</p>
<pre><code># ส่งจ้อความส่วนตัว
receiver_pk = PublicKey.from_bech32("npubคนรับ")
event = EventBuilder.encrypted_direct_msg(keys, receiver_pk, "ข้อความ", None).to_event(keys)
print(event.as_json())

# templateเปล่า
kind = Kind(เลข kind)
content = "..."
tags = []
builder = EventBuilder(kind, content, tags)


# POW
event = builder.to_pow_event(keys, 20)
print(f"POW event: {event.as_json()}")
</code></pre>
<p>ส่วนตัวผมมองว่าส่วนนี้แหละคือส่วนที่สนุกที่สุดของวันนี้ เพราะเป็นจุดที่เราสามารถนำมันออกไปต่อยอดได้มากที่สุด เช่นการเชื่อมต่อกับ service อื่น ๆ เช่น mempool.space เพื่อส่งค่าฟี bitcoin ให้เราผ่านแชท, ทำเกมง่าย ๆ เล่นกับเพื่อน ๆ หน้า timeline อย่าง cowdle หรือ หวย อย่างที่เห็นกันไปในช่วงก่อนหน้านี้ หรือใช้ทำงานกรรมกรแทนเรา เช่นการแจก badges ที่ทาง rightshift ได้ทำไปก่อนหน้า, bot relay notoshi, zapbot และอีกต่าง ๆ มากมาย</p>
<h3>filter</h3>
<p>ตัว filter เป็นคำสั่งที่ช่วยเรากรอง event ที่จะขอจาก relay ใช้เพื่อรับเฉพาะ event ที่เราต้องการเท่านั้น</p>
<pre><code>
f = (Filter()
     .pubkey(keys.public_key())
     .kinds([Kind(0), Kind.from_enum(KindEnum.TEXT_NOTE())])
     .custom_tag(SingleLetterTag.lowercase(Alphabet.J), ["test"])
     )
print(f.as_json())
# output: {"kinds":[0,1],"#j":["test"],"#p":["758dd30b7beef1ab9e7acb3c40449406c1321b7c79b63fff1909b812aecbe087"]}

f = f.kind(Kind(4)).custom_tag(SingleLetterTag.lowercase(Alphabet.J), ["append-new"])
print(f.as_json())
{"kinds":[0,1,4],"#j":["test","append-new"],"#p":["758dd30b7beef1ab9e7acb3c40449406c1321b7c79b63fff1909b812aecbe087"]}

#ตัวอย่างเช่นรับเฉพาะ event ของคนที่ใช้ notoshi relay
filter =Filter().kind(Kind(10002)).custom_tag(SingleLetterTag.lowercase(Alphabet.R), ["wss://relay.notoshi.win"])
events = client.get_events_of([filter], timedelta(seconds=30))
</code></pre>
<p>สองฟังก์ชันนี้เป็นตัวสำคัญในการทำบอทในส่วนต่อไปจะเป็นตัวเสริมต่าง ๆ ที่เพิ่มลูกเล่นให้บอทได้</p>
<h3>Metadata</h3>
<p>metadata มีไว้แก้ไขข้อมูลต่าง ๆ ในโปรไฟล์ของเรา</p>
<pre><code>metadata = Metadata().set_name("username")\
        .set_display_name("My Username")\
        .set_about("Description")\
        .set_picture("https://example.com/avatar.png")\
        .set_banner("https://example.com/banner.png")\
        .set_nip05("username@example.com")\
        .set_lud16("username@example.com")
# name = ชื้อผู้ใช่
# display_name = ชื่อที่จะแสดงให้คนอื่นเห็น (ถ้าช่องนี้ว่างมักจะโชว์ชื่อที่ใว่ในช่อง name)
# about = bio
# picture = รูปโปรไฟล์
# banner = รูปปก
# nip05 = Nostr addr
# lud16 = Lightning addr
</code></pre>
<h3>NWC</h3>
<p>NWC หรือ Nostr wallet connection มีไว้ใช้ในการเชื่อมต่อกับกระเป๋า ln ของเราเพื่อคุมกระเป๋าของเราผ่าน Nostr</p>
<pre><code># นำ NWC uri มาวาง
uri = NostrWalletConnectUri.parse("nostr+walletconnect://..")

# สร้าง client ในรูปแบบที่เพิ่มการ zap
keys = Keys.generate()
signer = NostrSigner.keys(keys)
zapper = NostrZapper.nwc(uri)
client = ClientBuilder().signer(signer).zapper(zapper).build()

client.add_relay("wss://relay.damus.io")
client.connect()

pk = PublicKey.from_bech32(" npub คนรับ")
client.zap(ZapEntity.public_key(pk), 1000, None)
</code></pre>
<h2>Bot template</h2>
<pre><code>
from nostr_sdk import Client, NostrSigner, Keys, Event, UnsignedEvent, Filter, \
    HandleNotification, Timestamp, nip04_decrypt, UnwrappedGift, init_logger, LogLevel, Kind, KindEnum
import time

init_logger(LogLevel.DEBUG)

# sk = SecretKey.from_bech32("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")
# keys = Keys(sk)
# OR
keys = Keys.parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")

sk = keys.secret_key()
pk = keys.public_key()
print(f"Bot public key: {pk.to_bech32()}")

signer = NostrSigner.keys(keys)
client = Client(signer)

client.add_relay("wss://relay.damus.io")
client.add_relay("wss://nostr.mom")
client.add_relay("wss://nostr.oxtr.dev")
client.connect()

now = Timestamp.now()

nip04_filter = Filter().pubkey(pk).kind(Kind.from_enum(KindEnum.ENCRYPTED_DIRECT_MESSAGE())).since(now)
nip59_filter = Filter().pubkey(pk).kind(Kind.from_enum(KindEnum.GIFT_WRAP())).since(
    Timestamp.from_secs(now.as_secs() - 60 * 60 * 24 * 7))  # NIP59 have a tweaked timestamp (in the past)
client.subscribe([nip04_filter, nip59_filter], None)


class NotificationHandler(HandleNotification):
    def handle(self, relay_url, subscription_id, event: Event):
        print(f"Received new event from {relay_url}: {event.as_json()}")
        if event.kind().match_enum(KindEnum.ENCRYPTED_DIRECT_MESSAGE()):
            print("Decrypting NIP04 event")
            try:
                msg = nip04_decrypt(sk, event.author(), event.content())
                print(f"Received new msg: {msg}")
                client.send_direct_msg(event.author(), f"Echo: {msg}", event.id())
            except Exception as e:
                print(f"Error during content NIP04 decryption: {e}")
        elif event.kind().match_enum(KindEnum.GIFT_WRAP()):
            print("Decrypting NIP59 event")
            try:
                # Extract rumor
                unwrapped_gift = UnwrappedGift.from_gift_wrap(keys, event)
                sender = unwrapped_gift.sender()
                rumor: UnsignedEvent = unwrapped_gift.rumor()

                # Check timestamp of rumor
                if rumor.created_at().as_secs() &gt;= now.as_secs():
                    if rumor.kind().match_enum(KindEnum.SEALED_DIRECT()):
                        msg = rumor.content()
                        print(f"Received new msg [sealed]: {msg}")
                        client.send_sealed_msg(sender, f"Echo: {msg}", None)
                    else:
                        print(f"{rumor.as_json()}")
            except Exception as e:
                print(f"Error during content NIP59 decryption: {e}")

    def handle_msg(self, relay_url, msg):
        None


abortable = client.handle_notifications(NotificationHandler())
# Optionally, to abort handle notifications look, call abortable.abort()

while True:
    time.sleep(5.0)
    # abortable.abort()
</code></pre>
<p>ผมหวังว่าบทความนี้จะมีประโยชน์กับคนอ่าน และคาดหวังที่จะได้เห็น service ต่าง ๆ ที่สร้างสรรค์เกิดขึ้นหลังจากนี้<br>Link เพิ่มเติมที่สำหรับศึกษาต่อ</p>
<ul>
<li><np-embed url="https://github.com/rust-nostr/nostr/tree/master"><a href="https://github.com/rust-nostr/nostr/tree/master">https://github.com/rust-nostr/nostr/tree/master</a></np-embed></li>
<li><np-embed url="https://github.com/nostr-protocol/nips"><a href="https://github.com/nostr-protocol/nips">https://github.com/nostr-protocol/nips</a></np-embed></li>
</ul>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<h2>สร้าง Nostr Bot ด้วย Python</h2>
<blockquote>
<p><em>อะแฮ่ม ขอชี้แจงไว้ก่อนว่า ผมเขียนเพื่อให้ตัวเองอ่านเพื่อวันไหนจะกลับมาทำต่อจะได้พอจำได้ว่าตัวเองทำอะไรลงไปบ้าง เพราะงั้นบางส่วนในบทความนี้อาจจะไม่ละเอียด หากลองทำตามแล้วติดตรงไหนอยากสอบถาม ติดต่อมาได้ที่ Nostr Address: <a href="https://nosta.me/nprofile1qy0hwumn8ghj7mn0wd68ytfsxvhxgmmjv9nxzcm5dae8jtn0wfnj7qgcwaehxw309aex2mrp0yhxumm5daeks6fwwa5kutcqypnd7czk9kfe4k5xzfpkfzv5tf8v78tzx34nm9rcm652xw8nyq7xgdzhmy5">kritta@rightshift.to</a> หรือลองค้นเพิ่มเติมใน link ท้ายบทความนะครับ</em></p>
</blockquote>
<p>อย่างที่หลาย ๆ คนน่าจะทราบกันดีอยู่แล้วว่า Nostr เป็น open protocol ที่ใคร ๆ ก็สามารถเข้ามามีส่วนร่วมในการพัฒนาได้ ทำให้มีโปรเจคต่าง ๆ เกิดขึ้นมากมาย โดยบทความในชุดนี้ผมจะหยิบโปรเจคต่าง ๆ ที่น่าสนใจมามาลองเล่น และนำมาเล่าสู่กันฟัง หวังว่าผู้ที่หลงเข้ามาอ่านจะได้ประโยชน์จากสิ่งนี้นะครับ ;)</p>
<p>โดยในวันนี้โปรเจคที่ผมหยิบมาคือ NDK (Nostr development kit) ผมหาไม่เจอว่าใครเป็นคนเริ่มโปรเจค แต่คนที่ดูแล repo นี้หลัก ๆ คือคุณ <a href="https://nosta.me/nprofile1qywhwumn8ghj7mn0wd68ytndw46xjmnewaskcmr9wshxxmmd9uq36amnwvaz7tmjv4kxz7fwd46hg6tw09mkzmrvv46zucm0d5hsqgrgmqgktyvpqzma5slu9rmarlqj24zxdcg3tzrtneamxfhktmzzwg2x3v53">yukibtc</a> เริ่มต้นเหมือนจะเริ่มจาก RUST แต่ตอนนี้เหมือนจะแตกไป swift, java, python เอาจริง ๆ ผมไม่รู้หรอกว่าใครเป็นคนทำภาษาไหนเพราะ contributors เขาเยอะมาก แต่ก็นั่นแหละ ขอบคุณที่สร้างอะไรสนุก ๆ แบบนี้ออกมาให้ได้เล่นนะครับ</p>
<p>โดยอย่างแรกที่เราต้องเริ่มคือการสั่ง pip install ตัว nostr sdk เพื่อใช่งาน สำหรับคนที่ไม่มี python ในเครื่องก็ไปลง python ก่อนด้วยนะ หรือจะใช้ online ผ่าน google colab ลองเล่นดูก่อนก็ได้</p>
<pre><code>pip install pip install nostr-sdk 
</code></pre>
<p>จากนั้นเราก็จะสามารถใช้งาน Nostr_sdk ได้แล้ว!!!<br>โดยการที่เราจะเข้ามาใช้งาน Nostr ได้นั้นเราจำเป็นต้องมี keys เพื่อเข้าสู่ระบบเสียก่อนงั้นเรามาเริ่มจากการสร้าง keys กันก่อน</p>
<pre><code>from nostr_sdk import  Keys
#เพียงคำสั่งนี้คำสั่งเดียวก็ได้ keys แล้วงั้นเหรอ!!
keys = Keys.generate()
#แยก keys ออกเป็น secret key (sk) และ public key (pk) 
sk = keys.secret_key()
pk = keys.public_key()
#ไหน ๆ ขอดู keys หน่อยสิ้
print(f"public key: {pk.to_bech32()}")
print(f"Secret key: {sk.to_bech32()}")
#output:
#public key: npub1wkxaxzmmamc6h8n6ev7yq3y5qmqnyxmu0xmrllcepxup9tktuzrsu646r0
#Secret key: nsec160gefyqkderqlnr545ps4d5th6pex3ducqgcev69z0rstqakkv9scvat97
</code></pre>
<p><em>note ถ้าสร้าง keys เสร็จแล้วเอาไปเก็บไว้ในพวก dot env จะปลอดภัยและสะดวกในการใช้ต่อมากกว่า</em></p>
<p>แล้วหลังจากได้ keys มาแล้วเราจำเป็นต้องกำหนด signer, client และ relay ที่เราจะใช้ในการรับ event ของเรา</p>
<pre><code># กำหนด keys ที่เราพึ่งสร้างให้เป็นตัว sign event
signer = NostrSigner.keys(keys)
# นำเข้า key ที่มีอยู่แล้ว
# app_keys = Keys.parse("nsec......")
# signer = NostrSigner.keys(app_keys)
# หรือใช้ NIP46 signer
# uri = NostrConnectUri.parse("bunker://.. or nostrconnect://..")
# nip46 = Nip46Signer(uri, app_keys, timedelta(seconds=60), None)
# signer = NostrSigner.nip46(nip46)
# กำหนด client ให้ใช้ signer ตัวนี้ (feel like log in)
client = Client(signer)

# เพิ่ม relays ที่จะเก็บ event
client.add_relays(["wss://relay.damus.io", "wss://siamstr.com", "wss://siamstr.com","wss://relay.notoshi.win"])
client.connect()
#ตั้งชื่อให้ account เราสักหน่อยเพื่อเช็คด้วยว่า เราเชื่อมต่อ relay ต่าง ๆ ผ่านมั้ย
client.set_metadata(Metadata().set_name("Testing หลาม ๆ"))
</code></pre>
<p>หลังจากกำหนดทุกอย่างเรียบร้อยแล้ว เรามาลองสร้างโพสต์แรกกันเลยดีกว่า</p>
<pre><code>#tag เพื่อเอาไว้เติมส่วนต่าง ๆ นอกจาก เนื้อหาของโน๊ต เช่นการ mention การใส่ hashtag
# p = mention
# t = hashtag
tag = Tag.parse(["p", "66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64"])
#ใส่เนื้อหาที่เราค้องการโพสต์
builder = EventBuilder.text_note("สวัสดีชาวทุ่ง ", [tag])
ส่ง event ไปให้ relay โลดดดด
client.send_event_builder(builder)
</code></pre>
<p>แล้วนอกจากโพสต์ตระกูล kind:1 แล้วเรายังโพสต์ kind อื่น ๆ ได้ด้วย</p>
<pre><code># ส่งจ้อความส่วนตัว
receiver_pk = PublicKey.from_bech32("npubคนรับ")
event = EventBuilder.encrypted_direct_msg(keys, receiver_pk, "ข้อความ", None).to_event(keys)
print(event.as_json())

# templateเปล่า
kind = Kind(เลข kind)
content = "..."
tags = []
builder = EventBuilder(kind, content, tags)


# POW
event = builder.to_pow_event(keys, 20)
print(f"POW event: {event.as_json()}")
</code></pre>
<p>ส่วนตัวผมมองว่าส่วนนี้แหละคือส่วนที่สนุกที่สุดของวันนี้ เพราะเป็นจุดที่เราสามารถนำมันออกไปต่อยอดได้มากที่สุด เช่นการเชื่อมต่อกับ service อื่น ๆ เช่น mempool.space เพื่อส่งค่าฟี bitcoin ให้เราผ่านแชท, ทำเกมง่าย ๆ เล่นกับเพื่อน ๆ หน้า timeline อย่าง cowdle หรือ หวย อย่างที่เห็นกันไปในช่วงก่อนหน้านี้ หรือใช้ทำงานกรรมกรแทนเรา เช่นการแจก badges ที่ทาง rightshift ได้ทำไปก่อนหน้า, bot relay notoshi, zapbot และอีกต่าง ๆ มากมาย</p>
<h3>filter</h3>
<p>ตัว filter เป็นคำสั่งที่ช่วยเรากรอง event ที่จะขอจาก relay ใช้เพื่อรับเฉพาะ event ที่เราต้องการเท่านั้น</p>
<pre><code>
f = (Filter()
     .pubkey(keys.public_key())
     .kinds([Kind(0), Kind.from_enum(KindEnum.TEXT_NOTE())])
     .custom_tag(SingleLetterTag.lowercase(Alphabet.J), ["test"])
     )
print(f.as_json())
# output: {"kinds":[0,1],"#j":["test"],"#p":["758dd30b7beef1ab9e7acb3c40449406c1321b7c79b63fff1909b812aecbe087"]}

f = f.kind(Kind(4)).custom_tag(SingleLetterTag.lowercase(Alphabet.J), ["append-new"])
print(f.as_json())
{"kinds":[0,1,4],"#j":["test","append-new"],"#p":["758dd30b7beef1ab9e7acb3c40449406c1321b7c79b63fff1909b812aecbe087"]}

#ตัวอย่างเช่นรับเฉพาะ event ของคนที่ใช้ notoshi relay
filter =Filter().kind(Kind(10002)).custom_tag(SingleLetterTag.lowercase(Alphabet.R), ["wss://relay.notoshi.win"])
events = client.get_events_of([filter], timedelta(seconds=30))
</code></pre>
<p>สองฟังก์ชันนี้เป็นตัวสำคัญในการทำบอทในส่วนต่อไปจะเป็นตัวเสริมต่าง ๆ ที่เพิ่มลูกเล่นให้บอทได้</p>
<h3>Metadata</h3>
<p>metadata มีไว้แก้ไขข้อมูลต่าง ๆ ในโปรไฟล์ของเรา</p>
<pre><code>metadata = Metadata().set_name("username")\
        .set_display_name("My Username")\
        .set_about("Description")\
        .set_picture("https://example.com/avatar.png")\
        .set_banner("https://example.com/banner.png")\
        .set_nip05("username@example.com")\
        .set_lud16("username@example.com")
# name = ชื้อผู้ใช่
# display_name = ชื่อที่จะแสดงให้คนอื่นเห็น (ถ้าช่องนี้ว่างมักจะโชว์ชื่อที่ใว่ในช่อง name)
# about = bio
# picture = รูปโปรไฟล์
# banner = รูปปก
# nip05 = Nostr addr
# lud16 = Lightning addr
</code></pre>
<h3>NWC</h3>
<p>NWC หรือ Nostr wallet connection มีไว้ใช้ในการเชื่อมต่อกับกระเป๋า ln ของเราเพื่อคุมกระเป๋าของเราผ่าน Nostr</p>
<pre><code># นำ NWC uri มาวาง
uri = NostrWalletConnectUri.parse("nostr+walletconnect://..")

# สร้าง client ในรูปแบบที่เพิ่มการ zap
keys = Keys.generate()
signer = NostrSigner.keys(keys)
zapper = NostrZapper.nwc(uri)
client = ClientBuilder().signer(signer).zapper(zapper).build()

client.add_relay("wss://relay.damus.io")
client.connect()

pk = PublicKey.from_bech32(" npub คนรับ")
client.zap(ZapEntity.public_key(pk), 1000, None)
</code></pre>
<h2>Bot template</h2>
<pre><code>
from nostr_sdk import Client, NostrSigner, Keys, Event, UnsignedEvent, Filter, \
    HandleNotification, Timestamp, nip04_decrypt, UnwrappedGift, init_logger, LogLevel, Kind, KindEnum
import time

init_logger(LogLevel.DEBUG)

# sk = SecretKey.from_bech32("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")
# keys = Keys(sk)
# OR
keys = Keys.parse("nsec1ufnus6pju578ste3v90xd5m2decpuzpql2295m3sknqcjzyys9ls0qlc85")

sk = keys.secret_key()
pk = keys.public_key()
print(f"Bot public key: {pk.to_bech32()}")

signer = NostrSigner.keys(keys)
client = Client(signer)

client.add_relay("wss://relay.damus.io")
client.add_relay("wss://nostr.mom")
client.add_relay("wss://nostr.oxtr.dev")
client.connect()

now = Timestamp.now()

nip04_filter = Filter().pubkey(pk).kind(Kind.from_enum(KindEnum.ENCRYPTED_DIRECT_MESSAGE())).since(now)
nip59_filter = Filter().pubkey(pk).kind(Kind.from_enum(KindEnum.GIFT_WRAP())).since(
    Timestamp.from_secs(now.as_secs() - 60 * 60 * 24 * 7))  # NIP59 have a tweaked timestamp (in the past)
client.subscribe([nip04_filter, nip59_filter], None)


class NotificationHandler(HandleNotification):
    def handle(self, relay_url, subscription_id, event: Event):
        print(f"Received new event from {relay_url}: {event.as_json()}")
        if event.kind().match_enum(KindEnum.ENCRYPTED_DIRECT_MESSAGE()):
            print("Decrypting NIP04 event")
            try:
                msg = nip04_decrypt(sk, event.author(), event.content())
                print(f"Received new msg: {msg}")
                client.send_direct_msg(event.author(), f"Echo: {msg}", event.id())
            except Exception as e:
                print(f"Error during content NIP04 decryption: {e}")
        elif event.kind().match_enum(KindEnum.GIFT_WRAP()):
            print("Decrypting NIP59 event")
            try:
                # Extract rumor
                unwrapped_gift = UnwrappedGift.from_gift_wrap(keys, event)
                sender = unwrapped_gift.sender()
                rumor: UnsignedEvent = unwrapped_gift.rumor()

                # Check timestamp of rumor
                if rumor.created_at().as_secs() &gt;= now.as_secs():
                    if rumor.kind().match_enum(KindEnum.SEALED_DIRECT()):
                        msg = rumor.content()
                        print(f"Received new msg [sealed]: {msg}")
                        client.send_sealed_msg(sender, f"Echo: {msg}", None)
                    else:
                        print(f"{rumor.as_json()}")
            except Exception as e:
                print(f"Error during content NIP59 decryption: {e}")

    def handle_msg(self, relay_url, msg):
        None


abortable = client.handle_notifications(NotificationHandler())
# Optionally, to abort handle notifications look, call abortable.abort()

while True:
    time.sleep(5.0)
    # abortable.abort()
</code></pre>
<p>ผมหวังว่าบทความนี้จะมีประโยชน์กับคนอ่าน และคาดหวังที่จะได้เห็น service ต่าง ๆ ที่สร้างสรรค์เกิดขึ้นหลังจากนี้<br>Link เพิ่มเติมที่สำหรับศึกษาต่อ</p>
<ul>
<li><np-embed url="https://github.com/rust-nostr/nostr/tree/master"><a href="https://github.com/rust-nostr/nostr/tree/master">https://github.com/rust-nostr/nostr/tree/master</a></np-embed></li>
<li><np-embed url="https://github.com/nostr-protocol/nips"><a href="https://github.com/nostr-protocol/nips">https://github.com/nostr-protocol/nips</a></np-embed></li>
</ul>
]]></itunes:summary>
      <itunes:image href="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1714632586167-YAKIHONNES3.jpg"/>
      </item>
      
      <item>
      <title><![CDATA[ฉลาม7วัน]]></title>
      <description><![CDATA[series หลาม 7 วันที่วาดโดย npub1wv2xqeejk8u67k5d06qe5xpc0at7wjj8myuhvqcsg2f60w5zjzas5uvnxp]]></description>
             <itunes:subtitle><![CDATA[series หลาม 7 วันที่วาดโดย npub1wv2xqeejk8u67k5d06qe5xpc0at7wjj8myuhvqcsg2f60w5zjzas5uvnxp]]></itunes:subtitle>
      <pubDate>Sun, 07 Apr 2024 02:49:16 GMT</pubDate>
      <link>https://kritta.npub.pro/post/nosli-1712204589681/</link>
      <comments>https://kritta.npub.pro/post/nosli-1712204589681/</comments>
      <guid isPermaLink="false">naddr1qqfkummnd35j6vfhxyeryvp5x5urjd3cxypzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4gu7qvcmk</guid>
      <category>nosli</category>
      
      <noteId>naddr1qqfkummnd35j6vfhxyeryvp5x5urjd3cxypzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4gu7qvcmk</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<p>#[3]<br>#[4]<br>#[5]<br>#[6]<br>#[7]<br>#[8]<br>#[9]</p>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<p>#[3]<br>#[4]<br>#[5]<br>#[6]<br>#[7]<br>#[8]<br>#[9]</p>
]]></itunes:summary>
      
      </item>
      
      <item>
      <title><![CDATA[[REVIEW] Primal, freeform On IOS]]></title>
      <description><![CDATA[ในบทความนี้เป็นการรีวิวการใช้ client ต่าง ๆ บน IOS ของผมและเพื่อน ๆ ที่ช่วยกันลองเล่นและทดสอบเพื่อหา client บน IOS ที่จะใช้ป้ายยาคนใหม่ ๆ ให้เขาไม่รู้สึกว่าการเข้ามาในทุ่งม่วงแห่งนี้เป็นเรื่องยาก เมื่อได้ทดลองแล้วเลยอยากมาแชร์ผลที่ได้กับทุก ๆ คนบน Nostr เพื่อเป็นแนวทางหรือเป็นส่วนประกอบการตัดสินใจในการเข้าไปลองเล่น client ใหม่ ๆ]]></description>
             <itunes:subtitle><![CDATA[ในบทความนี้เป็นการรีวิวการใช้ client ต่าง ๆ บน IOS ของผมและเพื่อน ๆ ที่ช่วยกันลองเล่นและทดสอบเพื่อหา client บน IOS ที่จะใช้ป้ายยาคนใหม่ ๆ ให้เขาไม่รู้สึกว่าการเข้ามาในทุ่งม่วงแห่งนี้เป็นเรื่องยาก เมื่อได้ทดลองแล้วเลยอยากมาแชร์ผลที่ได้กับทุก ๆ คนบน Nostr เพื่อเป็นแนวทางหรือเป็นส่วนประกอบการตัดสินใจในการเข้าไปลองเล่น client ใหม่ ๆ]]></itunes:subtitle>
      <pubDate>Mon, 23 Oct 2023 11:07:41 GMT</pubDate>
      <link>https://kritta.npub.pro/post/review_client1/</link>
      <comments>https://kritta.npub.pro/post/review_client1/</comments>
      <guid isPermaLink="false">naddr1qq88yetkd9jhwhmrd35k2mn5xypzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4guemky46</guid>
      <category>nostr</category>
      
        <media:content url="https://cdn.discordapp.com/attachments/1120171425433661440/1165969352005259365/a-purple-ostrich-in-a-meadow-full-of-fun-and-adven-upscaled.png?ex=6548c894&amp;is=65365394&amp;hm=674b41cb27807180a549500c7d5c29a4ab4d2c7e68ae3aee7b818aaa693159f5&amp;" medium="image"/>
        <enclosure 
          url="https://cdn.discordapp.com/attachments/1120171425433661440/1165969352005259365/a-purple-ostrich-in-a-meadow-full-of-fun-and-adven-upscaled.png?ex=6548c894&amp;is=65365394&amp;hm=674b41cb27807180a549500c7d5c29a4ab4d2c7e68ae3aee7b818aaa693159f5&amp;" length="0" 
          type="image/png" 
        />
      <noteId>naddr1qq88yetkd9jhwhmrd35k2mn5xypzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4guemky46</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<h2>[REVIEW] Primal, freeform On IOS</h2>
<p>ในบทความนี้เป็นการรีวิวการใช้ client ต่าง ๆ บน IOS ของผมและเพื่อน ๆ ที่ช่วยกันลองเล่นและทดสอบเพื่อหา client บน IOS ที่จะใช้ป้ายยาคนใหม่ ๆ ให้เขาไม่รู้สึกว่าการเข้ามาในทุ่งม่วงแห่งนี้เป็นเรื่องยาก เมื่อได้ทดลองแล้วเลยอยากมาแชร์ผลที่ได้กับทุก ๆ คนบน Nostr เพื่อเป็นแนวทางหรือเป็นส่วนประกอบการตัดสินใจในการเข้าไปลองเล่น client ใหม่ ๆ </p>
<blockquote>
<p>ทั้งนี้ทั้งนั้น สิ่งที่ปรากฏภายในบทความนี้เป็นเพียงแค่ความคิดเห็นของผู้เขียนและแอพต่าง ๆ ที่ลอง<br>เป็นเวอร์ชันก่อนวันที่ 23/10/2023 หากโหลดมาใช้แล้วไม่เหมือนในรีวิวแปลว่าแอพมันอัปเดตไปแล้วนะครับ</p>
</blockquote>
<h2>Primal</h2>
<p>Primal เป็นอีก client นึงที่มีฟังก์ชันต่าง ๆ ค่อนข้างครบครันและมี UX/UI ที่ดี สวยงามและปรับแต่งได้ในระดับหนึ่ง นอกจากนี้ยังสามารถ zap ผ่าน โน้ตต่าง ๆ ได้โดยตรงและนอกจากนี้ยังรองรับ one-click zap ผ่าน NWC ได้อีกด้วย ส่วนการดาวน์โหลดในปัจจุบันสามารถทำได้ดังนี้</p>
<blockquote>
<p>Primal ในตอนนี้ทาง IOS สามารถดาวน์โหลดได้ผ่านทาง TestFlight เท่านั้น โดยสามารถเข้าไปรับ redeem code ได้ทางเว็บไซต์ของ primal จากนั้นให้ปุ่มดาวน์โหลดบน navbar แล้วเลือก IOS จากนั้นจะมีหน้าต่างโปรแกรม TestFlight ขึ้นมาให้เราดาวน์โหลด</p>
</blockquote>
<ul>
<li><ul>
<li>หากไม่เคยใช้ TestFlight มาก่อน แนะนำว่าให้ทำการดาวน์โหลดและ login ให้เสร็จเรียบร้อยก่อนไปรับ redeem code บน primal<br>ส่วนในแง่ของ ข้อดี – ข้อเสีย ที่ผมพอสรุปได้จากการใช้งานมีประมาณนี้ครับ</li>
</ul>
</li>
</ul>
<h3>ข้อดี</h3>
<ul>
<li>UI สวยงาม ตัวแอปลื่นไหลไม่สะดุดรองรับฟังก์ชันพื้นฐานครบ</li>
<li>Zap ผ่านโน้ตได้ และรับรอง NWC เพื่อทำ one-click-zap ได้</li>
<li>มีการแจ้งเตือนครบครันและปรับแต่งได้ตามความต้องการ</li>
<li>สร้างฟีดของ # ต่าง ๆ ได้ (ตรงนี้จะแตกต่างจากการติดตาม # ของ client อื่น ๆ )</li>
<li>UI ต่าง ๆ ของแอพเช่น ขนาดตัวอักษรสามารถปรับขนาดได้</li>
</ul>
<h2>ข้อเสีย</h2>
<ul>
<li>จัดการรีเลย์ผ่านทางแอพไม่ได้ อาจต้องมี client อื่น ๆ บนเครื่องเพื่อทำการจัดการต่าง ๆ เกี่ยวกับรีเลย์</li>
<li>การแจ้งเตือนในบางครั้งซ้ำซ้อนมีแจ้งเตือนเดิม ๆ เด้งหลาย ๆ ครั้ง</li>
<li>การแสดงจำนวนเช่น ผู้ติดตาม, คนตอบกลับ, คนกดไลค์มากกว่าความเป็นจริง</li>
<li>Upload วีดีโอตรง ๆ ไม่ได้ (เป็นลิ้งได้ครับ)</li>
<li>เวลาเราโพสต์และติด tag event ของโพสต์เราจะไม่มี tag ในช่อง tag ทำให้คนที่ติดตาม tag บน client อื่น ๆ ไม่เห็นโพสต์เรา (ร้ายแรง)</li>
</ul>
<h3>ข้อสรุป</h3>
<p>Primal เป็นอีก client นึงที่เหมาะสมกับการแนะนำมือใหม่มาก ๆ ครับเพราะถ้าสมัครบน primal มันจะเก็บ keys เข้าไปในมือถือเราไม่ต้องให้เรา copy ไปเก็บเองเหมือน client อื่น ๆ และนอกจากนี้ยังไม่ต้องให้มือใหม่ปวดหัวกับการจัดการรีเลย์ในช่วงแรกที่เล่นได้อีกด้วย </p>
<h2>Freefrom</h2>
<p>สำหรับทวิตเตอร์ เอ้ย freefrom เป็นอีก client ที่ใช้งานง่าย UI เป็นที่คุ้นเคย (ทวิต) แบบแทบจะเหมือนกันเลย และสามารถใช้งานฟังก์ชันต่าง ๆ ได้เหมือนกับโซเชี่ยลมีเดียโดยทั่วไปจุดเด่นที่ชอบในตัวของ freeform คือการที่เราสามารถส่ง contact card และ album ให้กันได้ด้วย ส่วนการดาวน์โหลดในปัจจุบันสามารถทำได้ดังนี้</p>
<blockquote>
<p>ตอนนี้สามารถดาวน์โหลดได้ผ่านทาง App Store ได้ตรง ๆ เลยครับ รูปนกตัวอ้วนกว่านกฟ้านิดนึง</p>
</blockquote>
<h3>ข้อดี</h3>
<ul>
<li>UI สวยงาม ใช้งานง่าย และหลาย ๆ คนน่าจะคุ้นเคยกับ UI รูปแบบนี้อยู่แล้ว</li>
<li>ระบบ DM สวยและมีลูกเล่นเยอะเช่น การส่ง contact card, album</li>
<li>Reaction ด้วย emoji ได้หลากหลายเป็นพื้นฐานอยู่แล้ว</li>
</ul>
<h3>ข้อเสีย</h3>
<ul>
<li>ไม่สามารถ zap หรือทำอะไรเกี่ยวกับ Lightning ได้เลยบนแอพ</li>
<li>ฟังก์ชันต่าง ๆ ที่เล่นได้ค่อนข้างน้อย  ไม่รองรับ Follow # หรือการ Upload video ไม่ได้ (ต้องเป็นลิ้ง)</li>
</ul>
<h3>ข้อสรุป</h3>
<p>Freeform เป็น client ที่เหมาะสมกับการแนะนำมือใหม่มาก ๆ โดยเฉพาะกลุ่มคนที่ไม่ได้เข้าใจ Bitcoin หรือ lightning เข้ามาเริ่มก่อนได้ง่าย ๆ และหากเขาสร้างคุณค่าในสังคมมากพอที่คนอยากจะ zap ให้เขา เดี๋ยวเขาก็หาทางใช้ client อื่น ๆ เพื่อมารับ zap เอง ;)</p>
<hr>
<p>ทั้งนี้ที่บทความนี้เกิดขึ้นมาได้ต้องขอขอบคุณ <a href="https://njump.me/npub1mqcwu7muxz3kfvfyfdme47a579t8x0lm3jrjx5yxuf4sknnpe43q7rnz85">Jakk Goodday</a> ที่แนะนำ primal มา และขอบคุณ <a href="https://njump.me/npub1r6g3v8nd0xmu3w080qaeevwz5pzk3qfh7vdx7ayd7dv0szr96ywsh7dlap">🐰🤍</a> ที่ยอมกระโดดมาเล่น Nostr และ ยอมช่วยทดลองและมารีวิวช่วยกันเทสจนสามารถได้บทความนี้ขึ้นมา</p>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<h2>[REVIEW] Primal, freeform On IOS</h2>
<p>ในบทความนี้เป็นการรีวิวการใช้ client ต่าง ๆ บน IOS ของผมและเพื่อน ๆ ที่ช่วยกันลองเล่นและทดสอบเพื่อหา client บน IOS ที่จะใช้ป้ายยาคนใหม่ ๆ ให้เขาไม่รู้สึกว่าการเข้ามาในทุ่งม่วงแห่งนี้เป็นเรื่องยาก เมื่อได้ทดลองแล้วเลยอยากมาแชร์ผลที่ได้กับทุก ๆ คนบน Nostr เพื่อเป็นแนวทางหรือเป็นส่วนประกอบการตัดสินใจในการเข้าไปลองเล่น client ใหม่ ๆ </p>
<blockquote>
<p>ทั้งนี้ทั้งนั้น สิ่งที่ปรากฏภายในบทความนี้เป็นเพียงแค่ความคิดเห็นของผู้เขียนและแอพต่าง ๆ ที่ลอง<br>เป็นเวอร์ชันก่อนวันที่ 23/10/2023 หากโหลดมาใช้แล้วไม่เหมือนในรีวิวแปลว่าแอพมันอัปเดตไปแล้วนะครับ</p>
</blockquote>
<h2>Primal</h2>
<p>Primal เป็นอีก client นึงที่มีฟังก์ชันต่าง ๆ ค่อนข้างครบครันและมี UX/UI ที่ดี สวยงามและปรับแต่งได้ในระดับหนึ่ง นอกจากนี้ยังสามารถ zap ผ่าน โน้ตต่าง ๆ ได้โดยตรงและนอกจากนี้ยังรองรับ one-click zap ผ่าน NWC ได้อีกด้วย ส่วนการดาวน์โหลดในปัจจุบันสามารถทำได้ดังนี้</p>
<blockquote>
<p>Primal ในตอนนี้ทาง IOS สามารถดาวน์โหลดได้ผ่านทาง TestFlight เท่านั้น โดยสามารถเข้าไปรับ redeem code ได้ทางเว็บไซต์ของ primal จากนั้นให้ปุ่มดาวน์โหลดบน navbar แล้วเลือก IOS จากนั้นจะมีหน้าต่างโปรแกรม TestFlight ขึ้นมาให้เราดาวน์โหลด</p>
</blockquote>
<ul>
<li><ul>
<li>หากไม่เคยใช้ TestFlight มาก่อน แนะนำว่าให้ทำการดาวน์โหลดและ login ให้เสร็จเรียบร้อยก่อนไปรับ redeem code บน primal<br>ส่วนในแง่ของ ข้อดี – ข้อเสีย ที่ผมพอสรุปได้จากการใช้งานมีประมาณนี้ครับ</li>
</ul>
</li>
</ul>
<h3>ข้อดี</h3>
<ul>
<li>UI สวยงาม ตัวแอปลื่นไหลไม่สะดุดรองรับฟังก์ชันพื้นฐานครบ</li>
<li>Zap ผ่านโน้ตได้ และรับรอง NWC เพื่อทำ one-click-zap ได้</li>
<li>มีการแจ้งเตือนครบครันและปรับแต่งได้ตามความต้องการ</li>
<li>สร้างฟีดของ # ต่าง ๆ ได้ (ตรงนี้จะแตกต่างจากการติดตาม # ของ client อื่น ๆ )</li>
<li>UI ต่าง ๆ ของแอพเช่น ขนาดตัวอักษรสามารถปรับขนาดได้</li>
</ul>
<h2>ข้อเสีย</h2>
<ul>
<li>จัดการรีเลย์ผ่านทางแอพไม่ได้ อาจต้องมี client อื่น ๆ บนเครื่องเพื่อทำการจัดการต่าง ๆ เกี่ยวกับรีเลย์</li>
<li>การแจ้งเตือนในบางครั้งซ้ำซ้อนมีแจ้งเตือนเดิม ๆ เด้งหลาย ๆ ครั้ง</li>
<li>การแสดงจำนวนเช่น ผู้ติดตาม, คนตอบกลับ, คนกดไลค์มากกว่าความเป็นจริง</li>
<li>Upload วีดีโอตรง ๆ ไม่ได้ (เป็นลิ้งได้ครับ)</li>
<li>เวลาเราโพสต์และติด tag event ของโพสต์เราจะไม่มี tag ในช่อง tag ทำให้คนที่ติดตาม tag บน client อื่น ๆ ไม่เห็นโพสต์เรา (ร้ายแรง)</li>
</ul>
<h3>ข้อสรุป</h3>
<p>Primal เป็นอีก client นึงที่เหมาะสมกับการแนะนำมือใหม่มาก ๆ ครับเพราะถ้าสมัครบน primal มันจะเก็บ keys เข้าไปในมือถือเราไม่ต้องให้เรา copy ไปเก็บเองเหมือน client อื่น ๆ และนอกจากนี้ยังไม่ต้องให้มือใหม่ปวดหัวกับการจัดการรีเลย์ในช่วงแรกที่เล่นได้อีกด้วย </p>
<h2>Freefrom</h2>
<p>สำหรับทวิตเตอร์ เอ้ย freefrom เป็นอีก client ที่ใช้งานง่าย UI เป็นที่คุ้นเคย (ทวิต) แบบแทบจะเหมือนกันเลย และสามารถใช้งานฟังก์ชันต่าง ๆ ได้เหมือนกับโซเชี่ยลมีเดียโดยทั่วไปจุดเด่นที่ชอบในตัวของ freeform คือการที่เราสามารถส่ง contact card และ album ให้กันได้ด้วย ส่วนการดาวน์โหลดในปัจจุบันสามารถทำได้ดังนี้</p>
<blockquote>
<p>ตอนนี้สามารถดาวน์โหลดได้ผ่านทาง App Store ได้ตรง ๆ เลยครับ รูปนกตัวอ้วนกว่านกฟ้านิดนึง</p>
</blockquote>
<h3>ข้อดี</h3>
<ul>
<li>UI สวยงาม ใช้งานง่าย และหลาย ๆ คนน่าจะคุ้นเคยกับ UI รูปแบบนี้อยู่แล้ว</li>
<li>ระบบ DM สวยและมีลูกเล่นเยอะเช่น การส่ง contact card, album</li>
<li>Reaction ด้วย emoji ได้หลากหลายเป็นพื้นฐานอยู่แล้ว</li>
</ul>
<h3>ข้อเสีย</h3>
<ul>
<li>ไม่สามารถ zap หรือทำอะไรเกี่ยวกับ Lightning ได้เลยบนแอพ</li>
<li>ฟังก์ชันต่าง ๆ ที่เล่นได้ค่อนข้างน้อย  ไม่รองรับ Follow # หรือการ Upload video ไม่ได้ (ต้องเป็นลิ้ง)</li>
</ul>
<h3>ข้อสรุป</h3>
<p>Freeform เป็น client ที่เหมาะสมกับการแนะนำมือใหม่มาก ๆ โดยเฉพาะกลุ่มคนที่ไม่ได้เข้าใจ Bitcoin หรือ lightning เข้ามาเริ่มก่อนได้ง่าย ๆ และหากเขาสร้างคุณค่าในสังคมมากพอที่คนอยากจะ zap ให้เขา เดี๋ยวเขาก็หาทางใช้ client อื่น ๆ เพื่อมารับ zap เอง ;)</p>
<hr>
<p>ทั้งนี้ที่บทความนี้เกิดขึ้นมาได้ต้องขอขอบคุณ <a href="https://njump.me/npub1mqcwu7muxz3kfvfyfdme47a579t8x0lm3jrjx5yxuf4sknnpe43q7rnz85">Jakk Goodday</a> ที่แนะนำ primal มา และขอบคุณ <a href="https://njump.me/npub1r6g3v8nd0xmu3w080qaeevwz5pzk3qfh7vdx7ayd7dv0szr96ywsh7dlap">🐰🤍</a> ที่ยอมกระโดดมาเล่น Nostr และ ยอมช่วยทดลองและมารีวิวช่วยกันเทสจนสามารถได้บทความนี้ขึ้นมา</p>
]]></itunes:summary>
      <itunes:image href="https://cdn.discordapp.com/attachments/1120171425433661440/1165969352005259365/a-purple-ostrich-in-a-meadow-full-of-fun-and-adven-upscaled.png?ex=6548c894&amp;is=65365394&amp;hm=674b41cb27807180a549500c7d5c29a4ab4d2c7e68ae3aee7b818aaa693159f5&amp;"/>
      </item>
      
      <item>
      <title><![CDATA[Nostrverse: เครื่องมือต่าง ๆ ที่ช่วยสร้างสรรค์ประสบการณ์ใหม่ ๆ บน Nostr]]></title>
      <description><![CDATA[Nostrverse: เครื่องมือต่าง ๆ ที่ช่วยสร้างสรรค์ประสบการณ์]]></description>
             <itunes:subtitle><![CDATA[Nostrverse: เครื่องมือต่าง ๆ ที่ช่วยสร้างสรรค์ประสบการณ์]]></itunes:subtitle>
      <pubDate>Mon, 16 Oct 2023 08:37:39 GMT</pubDate>
      <link>https://kritta.npub.pro/post/lucndqfgqvak-_m-71jwc/</link>
      <comments>https://kritta.npub.pro/post/lucndqfgqvak-_m-71jwc/</comments>
      <guid isPermaLink="false">naddr1qq25ca2rfej9zej8w9myz6edtaxj6de3fft5xq3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65w0lqs4p</guid>
      <category>หลามมันร้าย</category>
      
        <media:content url="Nostrverse: เครื่องมือต่าง ๆ ที่ช่วยสร้างสรรค์ประสบการณ์" medium="image"/>
        <enclosure 
          url="Nostrverse: เครื่องมือต่าง ๆ ที่ช่วยสร้างสรรค์ประสบการณ์" length="0" 
          type="" 
        />
      <noteId>naddr1qq25ca2rfej9zej8w9myz6edtaxj6de3fft5xq3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65w0lqs4p</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<p>Nostr หรือ Notes and Other Stuff Transmitted by Relays เป็นโปรโตคอล<br>โซเชี่ยลเน็ตเวิร์ครูปแบบใหม่ที่ไร้ศูนย์กลางซึ่งทำให้ใคร ๆ ก็สามารถเข้ามาร่วมพัฒนาและสร้างสรรค์สิ่งใหม่ ๆ บน Nostr ได้ทำให้มีเครื่องมือต่าง ๆ มากมายที่ช่วยให้เราได้รับประสบการณ์ที่ดีขึ้นในการท่องไปในจักรวาลของ Nostr ซึ่งในบทความนี้จะแนะนำเครื่องมือต่าง ๆ บน Nostr ที่ช่วยเพิ่มความสะดวกสบาย และ สร้างสรรค์ประสบการณ์ใหม่ ๆ ให้กับการใช้งาน Nostr โดยมีเครื่องมือต่าง ๆ ดังต่อไปนี้</p>
<h2>Listr : ตัวช่วยในการจัดการหน้าฟีด</h2>
<p>Listr เป็นเครื่องมือที่ช่วยให้เราสามารถสร้าง list ต่าง ๆ เพื่อจัดกลุ่มคนที่เราติดตามหรือโน๊ตที่เราชื่นชอบให้เป็นหมวดหมู่ และความพิเศษของ Listr คือเราสามารถที่จะแชร์ list ของเราให้แก่เพื่อน ๆ ของเราได้ด้วย</p>
<ul>
<li><p>เพียงแค่เราเข้าไปที่ <a href="https://listr.lol/">Listr.lol</a></p>
</li>
<li><p>กรอกข้อมูลลงในช่องต่าง ๆ และเพิ่ม account หรือ note ที่เราต้องการสร้าง list </p>
</li>
<li><p>กด Publish new list</p>
</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697440254567-YAKIHONNES3.png" alt="image"></p>
<ul>
<li>จากนั้นเมื่อเราสามารถนำ address ที่ได้มาไปแชร์บน client ที่รองรับเพื่อส่งต่อให้คนอื่น ๆ ได้เลยครับ<br>ตัวอย่าง:<br><np-embed nostr="naddr1qqzx6at5v5q3wamnwvaz7tmjv4kxz7fwwd5kzmtnw3ezucm0d5qs6amnwvaz7tmwdaejumr0dspzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4xqnfquht"><a href="https://njump.me/naddr1qqzx6at5v5q3wamnwvaz7tmjv4kxz7fwwd5kzmtnw3ezucm0d5qs6amnwvaz7tmwdaejumr0dspzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4xqnfquht">nostr:naddr1qqzx6at5v5q3wamnwvaz7tmjv4kxz7fwwd5kzmtnw3ezucm0d5qs6amnwvaz7tmwdaejumr0dspzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4xqnfquht</a></np-embed></li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697441593143-YAKIHONNES3.png" alt="image"><br>list รวมเหล่า shitcoin หิวเงินที่มาหากินบนนี้ mute ไปได้เลยครับ</p>
<h2>Badges.page : เหรียญตราสุดเท่บนโปรไฟล์</h2>
<p>Badges เป็นอีกลูกเล่นหนึ่งของ nostr ที่ทำให้เราสามารถสร้างและส่ง badge ให้เพื่อน ๆ เพื่อเป็นสัญลักษณ์ หรือเพื่อความสวยงามของโปรไฟล์ จริง ๆ ที่ชอบเพราะมันเท่ดีเวลาเปิดหน้าโปรไฟล์</p>
<p><img src="https://image.nostr.build/00b5c0b54c3ee5131d309e1fec0c26f5f83de31653f523bd1be774531d35b797.png" alt="image"></p>
<p>ส่วนวิธีการสร้าง badge สามารถทำได้ตามขั้นตอนต่อไปนี้เลยครับ</p>
<ul>
<li>เข้าเว็บ <a href="https://badges.page/">Badges.page</a> และ login ให้เรียบร้อย</li>
<li>จากนั้นคลิกคำว่า new บนหัวมุมขวาใกล้ ๆ โปรไฟล์</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697442328181-YAKIHONNES3.png" alt="image"></p>
<ul>
<li>และใส่ข้อมูลต่าง ๆ ที่เราต้องการลงไป จากนั้นกด save and Publish</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697442516997-YAKIHONNES3.png" alt="image"></p>
<ul>
<li><p>จากนั้นให้เราเข้าไปที่หน้าของ badge นั้น ๆ และใส่ nip-05 หรือ npub ของคนที่เราต้องการให้ badge ลงไป และกด Award badge ได้เลยครับ<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697443319588-YAKIHONNES3.png" alt="image"></p>
</li>
<li><p>เมื่อเราทำการ award badge เรียบร้อยแล้ว ให้คนที่เราส่งให้เข้าไปรับที่ <a href="https://badges.page/">Badges.page</a> โดยเข้าไปที่หน้าโปรไฟล์ เลือก awarded และกด accept<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697443796983-YAKIHONNES3.png" alt="image"></p>
</li>
</ul>
<p>เพียงเท่านี้เมื่อเราเข้าไปท่องโลกของ nostr ผ่าน client ที่รองรับเราก็จะมี badge เท่ ๆ โชว์อยู่ที่หน้าโปรไฟล์แล้ว!</p>
<h2>ZapGoals : เครื่องมือระดมทุนสุดเจ๋งบนNostr ! !</h2>
<p>zapGoals เป็นเครื่องมือที่ช่วยให้เราสามารถสร้างเป้าหมายในการระดมทุนเพื่อทำสิ่งต่าง ๆ ได้นอกจากนี้ยังสามารถตั้งผู้รับผลประโยชน์และแสดงผู้ที่เข้ามาร่วมบริจาคให้กับการระดมทุนในครั้งนั้น ๆ ได้อีกด้วย ส่วนวิธีการสร้าง goal สามารถทำตามขั้นตอนข้างล่างนี้ได้เลย</p>
<ul>
<li>เข้าไปที่เว็บ <a href="https://goals-silk.vercel.app/">goals-silk.vercel.app</a></li>
<li>จากนั้นเมื่อเรา login เรียบร้อยแล้ว กดที่ profile และกด new</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697444785527-YAKIHONNES3.png" alt="image"></p>
<ul>
<li>จากนั้นให้เราใส่ข้อมูลต่าง ๆ ที่เราต้องการให้แสดงลงไป<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697444946992-YAKIHONNES3.png" alt="image"></li>
<li>และเราก็จะได้ goal ที่มีหน้าตาแบบนี้<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697445007455-YAKIHONNES3.png" alt="image"></li>
</ul>
<h3>แล้วเราสามารถเอา goal พวกนี้ไปทำอะไรได้บ้างละ ?</h3>
<p>เราสามารถนำ link ของ goal ที่เราสร้างไปใส่ใน live stream บน zap.stream, บน long form content ผ่านทาง habla, ใน client ต่าง ๆ ที่รองรับ, หรือแม้แต่ใน badges ที่ได้กล่าวถึงข้างต้น </p>
<hr>
<p>Nostrverse เป็นชุดบทความที่ผมจะเล่าถึงสิ่งต่าง ๆ ที่เจอและได้ไปทดลองใช้งานมา หวังว่ามันจะมีประโยชน์กับผู้อ่านไม่มากก็น้อยนะครับ ขอให้มีความสุขในทุ่งแห่งอิสรภาพแห่งนี้ครับ</p>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<p>Nostr หรือ Notes and Other Stuff Transmitted by Relays เป็นโปรโตคอล<br>โซเชี่ยลเน็ตเวิร์ครูปแบบใหม่ที่ไร้ศูนย์กลางซึ่งทำให้ใคร ๆ ก็สามารถเข้ามาร่วมพัฒนาและสร้างสรรค์สิ่งใหม่ ๆ บน Nostr ได้ทำให้มีเครื่องมือต่าง ๆ มากมายที่ช่วยให้เราได้รับประสบการณ์ที่ดีขึ้นในการท่องไปในจักรวาลของ Nostr ซึ่งในบทความนี้จะแนะนำเครื่องมือต่าง ๆ บน Nostr ที่ช่วยเพิ่มความสะดวกสบาย และ สร้างสรรค์ประสบการณ์ใหม่ ๆ ให้กับการใช้งาน Nostr โดยมีเครื่องมือต่าง ๆ ดังต่อไปนี้</p>
<h2>Listr : ตัวช่วยในการจัดการหน้าฟีด</h2>
<p>Listr เป็นเครื่องมือที่ช่วยให้เราสามารถสร้าง list ต่าง ๆ เพื่อจัดกลุ่มคนที่เราติดตามหรือโน๊ตที่เราชื่นชอบให้เป็นหมวดหมู่ และความพิเศษของ Listr คือเราสามารถที่จะแชร์ list ของเราให้แก่เพื่อน ๆ ของเราได้ด้วย</p>
<ul>
<li><p>เพียงแค่เราเข้าไปที่ <a href="https://listr.lol/">Listr.lol</a></p>
</li>
<li><p>กรอกข้อมูลลงในช่องต่าง ๆ และเพิ่ม account หรือ note ที่เราต้องการสร้าง list </p>
</li>
<li><p>กด Publish new list</p>
</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697440254567-YAKIHONNES3.png" alt="image"></p>
<ul>
<li>จากนั้นเมื่อเราสามารถนำ address ที่ได้มาไปแชร์บน client ที่รองรับเพื่อส่งต่อให้คนอื่น ๆ ได้เลยครับ<br>ตัวอย่าง:<br><np-embed nostr="naddr1qqzx6at5v5q3wamnwvaz7tmjv4kxz7fwwd5kzmtnw3ezucm0d5qs6amnwvaz7tmwdaejumr0dspzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4xqnfquht"><a href="https://njump.me/naddr1qqzx6at5v5q3wamnwvaz7tmjv4kxz7fwwd5kzmtnw3ezucm0d5qs6amnwvaz7tmwdaejumr0dspzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4xqnfquht">nostr:naddr1qqzx6at5v5q3wamnwvaz7tmjv4kxz7fwwd5kzmtnw3ezucm0d5qs6amnwvaz7tmwdaejumr0dspzqeklvptzmyu6m2rpysmy3x295nk0r43rg6eaj3uda29r8rejq0ryqvzqqqr4xqnfquht</a></np-embed></li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697441593143-YAKIHONNES3.png" alt="image"><br>list รวมเหล่า shitcoin หิวเงินที่มาหากินบนนี้ mute ไปได้เลยครับ</p>
<h2>Badges.page : เหรียญตราสุดเท่บนโปรไฟล์</h2>
<p>Badges เป็นอีกลูกเล่นหนึ่งของ nostr ที่ทำให้เราสามารถสร้างและส่ง badge ให้เพื่อน ๆ เพื่อเป็นสัญลักษณ์ หรือเพื่อความสวยงามของโปรไฟล์ จริง ๆ ที่ชอบเพราะมันเท่ดีเวลาเปิดหน้าโปรไฟล์</p>
<p><img src="https://image.nostr.build/00b5c0b54c3ee5131d309e1fec0c26f5f83de31653f523bd1be774531d35b797.png" alt="image"></p>
<p>ส่วนวิธีการสร้าง badge สามารถทำได้ตามขั้นตอนต่อไปนี้เลยครับ</p>
<ul>
<li>เข้าเว็บ <a href="https://badges.page/">Badges.page</a> และ login ให้เรียบร้อย</li>
<li>จากนั้นคลิกคำว่า new บนหัวมุมขวาใกล้ ๆ โปรไฟล์</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697442328181-YAKIHONNES3.png" alt="image"></p>
<ul>
<li>และใส่ข้อมูลต่าง ๆ ที่เราต้องการลงไป จากนั้นกด save and Publish</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697442516997-YAKIHONNES3.png" alt="image"></p>
<ul>
<li><p>จากนั้นให้เราเข้าไปที่หน้าของ badge นั้น ๆ และใส่ nip-05 หรือ npub ของคนที่เราต้องการให้ badge ลงไป และกด Award badge ได้เลยครับ<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697443319588-YAKIHONNES3.png" alt="image"></p>
</li>
<li><p>เมื่อเราทำการ award badge เรียบร้อยแล้ว ให้คนที่เราส่งให้เข้าไปรับที่ <a href="https://badges.page/">Badges.page</a> โดยเข้าไปที่หน้าโปรไฟล์ เลือก awarded และกด accept<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697443796983-YAKIHONNES3.png" alt="image"></p>
</li>
</ul>
<p>เพียงเท่านี้เมื่อเราเข้าไปท่องโลกของ nostr ผ่าน client ที่รองรับเราก็จะมี badge เท่ ๆ โชว์อยู่ที่หน้าโปรไฟล์แล้ว!</p>
<h2>ZapGoals : เครื่องมือระดมทุนสุดเจ๋งบนNostr ! !</h2>
<p>zapGoals เป็นเครื่องมือที่ช่วยให้เราสามารถสร้างเป้าหมายในการระดมทุนเพื่อทำสิ่งต่าง ๆ ได้นอกจากนี้ยังสามารถตั้งผู้รับผลประโยชน์และแสดงผู้ที่เข้ามาร่วมบริจาคให้กับการระดมทุนในครั้งนั้น ๆ ได้อีกด้วย ส่วนวิธีการสร้าง goal สามารถทำตามขั้นตอนข้างล่างนี้ได้เลย</p>
<ul>
<li>เข้าไปที่เว็บ <a href="https://goals-silk.vercel.app/">goals-silk.vercel.app</a></li>
<li>จากนั้นเมื่อเรา login เรียบร้อยแล้ว กดที่ profile และกด new</li>
</ul>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697444785527-YAKIHONNES3.png" alt="image"></p>
<ul>
<li>จากนั้นให้เราใส่ข้อมูลต่าง ๆ ที่เราต้องการให้แสดงลงไป<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697444946992-YAKIHONNES3.png" alt="image"></li>
<li>และเราก็จะได้ goal ที่มีหน้าตาแบบนี้<img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1697445007455-YAKIHONNES3.png" alt="image"></li>
</ul>
<h3>แล้วเราสามารถเอา goal พวกนี้ไปทำอะไรได้บ้างละ ?</h3>
<p>เราสามารถนำ link ของ goal ที่เราสร้างไปใส่ใน live stream บน zap.stream, บน long form content ผ่านทาง habla, ใน client ต่าง ๆ ที่รองรับ, หรือแม้แต่ใน badges ที่ได้กล่าวถึงข้างต้น </p>
<hr>
<p>Nostrverse เป็นชุดบทความที่ผมจะเล่าถึงสิ่งต่าง ๆ ที่เจอและได้ไปทดลองใช้งานมา หวังว่ามันจะมีประโยชน์กับผู้อ่านไม่มากก็น้อยนะครับ ขอให้มีความสุขในทุ่งแห่งอิสรภาพแห่งนี้ครับ</p>
]]></itunes:summary>
      <itunes:image href="Nostrverse: เครื่องมือต่าง ๆ ที่ช่วยสร้างสรรค์ประสบการณ์"/>
      </item>
      
      <item>
      <title><![CDATA[Nostore: Extensions ใน safari ที่ช่วยให้คุณท่องโลกของ Nostr ผ่าน IOS ได้ง่ายขึ้น]]></title>
      <description><![CDATA[สอนใช้งานการใช้งาน Nostore: Extensions ใน safari ที่ช่วยให้คุณท่องโลกของ Nostr ผ่าน IOS ได้ง่ายขึ้น]]></description>
             <itunes:subtitle><![CDATA[สอนใช้งานการใช้งาน Nostore: Extensions ใน safari ที่ช่วยให้คุณท่องโลกของ Nostr ผ่าน IOS ได้ง่ายขึ้น]]></itunes:subtitle>
      <pubDate>Sat, 14 Oct 2023 12:52:53 GMT</pubDate>
      <link>https://kritta.npub.pro/post/nostore_guide/</link>
      <comments>https://kritta.npub.pro/post/nostore_guide/</comments>
      <guid isPermaLink="false">naddr1qqx5ummnw3hhye2lga6kjer9qgsxdhmq2cke8xk6scfyxeyfj3dyancavg6xk0v50r023gec7vsrceqrqsqqqa28qvgrjh</guid>
      <category>nostr</category>
      
        <media:content url="https://image.nostr.build/3164f3dc0a5ad4d47ded5d80eeb346d4f9df710d9baa081f6a36e25c0e84c19b.jpg" medium="image"/>
        <enclosure 
          url="https://image.nostr.build/3164f3dc0a5ad4d47ded5d80eeb346d4f9df710d9baa081f6a36e25c0e84c19b.jpg" length="0" 
          type="image/jpeg" 
        />
      <noteId>naddr1qqx5ummnw3hhye2lga6kjer9qgsxdhmq2cke8xk6scfyxeyfj3dyancavg6xk0v50r023gec7vsrceqrqsqqqa28qvgrjh</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<p>Nostore คือ extension บน safari ที่ทำให้เราสามารถใช้งาน NIP-07(window.nostr capability for web browsers) ผ่านอุปกรณ์ต่าง ๆ ของ apple ได้ซึ่งสามารถอำนวยความสะดวกให้เหล่าสาวก IPhone สามารถเข้าถึงส่วนต่าง ๆ ของจักรวาล NOSTR โดยเฉพาะในส่วนของ " OS(Other Stuff) " ได้ง่ายและปลอดภัยมากขึ้น โดยมีขั้นตอนดังต่อไปนี้</p>
<ol>
<li>ให้ทำการดาวน์โหลดแอปพลิเคชั่น Nostore ผ่าน App store!<br><a href="https://image.nostr.build/3164f3dc0a5ad4d47ded5d80eeb346d4f9df710d9baa081f6a36e25c0e84c19b.jpg"></a></li>
<li>ให้ทำการเข้าไปในแอปในขั้นตอนนี้จะมีไกด์วิธีใช้งานในแต่ละ device แต่ถ้าไม่อยากอ่านก็ทำตามโน๊ตนี้ต่อก็ได้ครับ<br> <a href="https://image.nostr.build/5b00b126473a5eba697d46c7980ed44374526a57de75e5ebd45a7a0d5c590e6d.jpg"></a></li>
<li>ให้เราเข้าไปใน safari  และ กดรูปจิ๊กซอที่แถบ URL และ เลือก Manage Extensions กดเปิด Nostore<br> <a href="https://image.nostr.build/92a833d741901134590dddd64f95844cb909cafa744a8b8e0d80ef3624e8133c.jpg"></a></li>
<li>จากนั้นให้เรากด NEW และ ใส่ข้อมูลต่าง ๆ ลงไป<ul>
<li>profile name อันนี้แล้วแต่เราจะตั้งเลยครับจะมีประโยชน์ถ้าเราเล่นหลายแอค</li>
<li>relay อาจเพิ่มลำบากนิดนึงแต่แนะนำให้เพิ่มให้ครบตามที่เราใช้ใน platform ต่าง ๆ ครับ <a href="https://media.discordapp.net/attachments/895541090977984563/1162733789873721455/image.png?ex=653d033a&amp;is=652a8e3a&amp;hm=f19e0a59537524b87d170675356e7baff4da6af04cb0e0dfa79e0c28002fa448&amp;=&amp;width=1102&amp;height=1108"></a></li>
</ul>
</li>
</ol>
<hr>
<p>หลังจากนั้นเมื่อเราเข้าเว็บต่าง ๆ ที่รองรับการเข้าสู่ระบบด้วย NIP-07 ตัว extension จะเด้งขึ้นมาให้เรากด allow ครับ(หน้าตามันจะหน้าเกลียดหน่อย ๆ นะครับ)<br>จากนั้นเมื่อเราก็สามารถเข้าเว็บอย่าง zap.stream , habla, yaki, listr หรือ web-base client ต่าง ๆ บน IOS device ของเราได้โดยไม่ต้องนำ nsec ของเราไปวางบนเว็บนั้น ๆ แล้ว</p>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<p>Nostore คือ extension บน safari ที่ทำให้เราสามารถใช้งาน NIP-07(window.nostr capability for web browsers) ผ่านอุปกรณ์ต่าง ๆ ของ apple ได้ซึ่งสามารถอำนวยความสะดวกให้เหล่าสาวก IPhone สามารถเข้าถึงส่วนต่าง ๆ ของจักรวาล NOSTR โดยเฉพาะในส่วนของ " OS(Other Stuff) " ได้ง่ายและปลอดภัยมากขึ้น โดยมีขั้นตอนดังต่อไปนี้</p>
<ol>
<li>ให้ทำการดาวน์โหลดแอปพลิเคชั่น Nostore ผ่าน App store!<br><a href="https://image.nostr.build/3164f3dc0a5ad4d47ded5d80eeb346d4f9df710d9baa081f6a36e25c0e84c19b.jpg"></a></li>
<li>ให้ทำการเข้าไปในแอปในขั้นตอนนี้จะมีไกด์วิธีใช้งานในแต่ละ device แต่ถ้าไม่อยากอ่านก็ทำตามโน๊ตนี้ต่อก็ได้ครับ<br> <a href="https://image.nostr.build/5b00b126473a5eba697d46c7980ed44374526a57de75e5ebd45a7a0d5c590e6d.jpg"></a></li>
<li>ให้เราเข้าไปใน safari  และ กดรูปจิ๊กซอที่แถบ URL และ เลือก Manage Extensions กดเปิด Nostore<br> <a href="https://image.nostr.build/92a833d741901134590dddd64f95844cb909cafa744a8b8e0d80ef3624e8133c.jpg"></a></li>
<li>จากนั้นให้เรากด NEW และ ใส่ข้อมูลต่าง ๆ ลงไป<ul>
<li>profile name อันนี้แล้วแต่เราจะตั้งเลยครับจะมีประโยชน์ถ้าเราเล่นหลายแอค</li>
<li>relay อาจเพิ่มลำบากนิดนึงแต่แนะนำให้เพิ่มให้ครบตามที่เราใช้ใน platform ต่าง ๆ ครับ <a href="https://media.discordapp.net/attachments/895541090977984563/1162733789873721455/image.png?ex=653d033a&amp;is=652a8e3a&amp;hm=f19e0a59537524b87d170675356e7baff4da6af04cb0e0dfa79e0c28002fa448&amp;=&amp;width=1102&amp;height=1108"></a></li>
</ul>
</li>
</ol>
<hr>
<p>หลังจากนั้นเมื่อเราเข้าเว็บต่าง ๆ ที่รองรับการเข้าสู่ระบบด้วย NIP-07 ตัว extension จะเด้งขึ้นมาให้เรากด allow ครับ(หน้าตามันจะหน้าเกลียดหน่อย ๆ นะครับ)<br>จากนั้นเมื่อเราก็สามารถเข้าเว็บอย่าง zap.stream , habla, yaki, listr หรือ web-base client ต่าง ๆ บน IOS device ของเราได้โดยไม่ต้องนำ nsec ของเราไปวางบนเว็บนั้น ๆ แล้ว</p>
]]></itunes:summary>
      <itunes:image href="https://image.nostr.build/3164f3dc0a5ad4d47ded5d80eeb346d4f9df710d9baa081f6a36e25c0e84c19b.jpg"/>
      </item>
      
      <item>
      <title><![CDATA[Ransomware มันจะเท่าไหร่กันเชียว]]></title>
      <description><![CDATA[ความทรงจำในแดนอาทิตย์อุทัยที่มีแต่งาน]]></description>
             <itunes:subtitle><![CDATA[ความทรงจำในแดนอาทิตย์อุทัยที่มีแต่งาน]]></itunes:subtitle>
      <pubDate>Sat, 30 Nov 56548 13:20:50 GMT</pubDate>
      <link>https://kritta.npub.pro/post/8eodlc9aest5yv9ssvgvo/</link>
      <comments>https://kritta.npub.pro/post/8eodlc9aest5yv9ssvgvo/</comments>
      <guid isPermaLink="false">naddr1qq2nset0v3xyxwtpv4e4gd2ewcu4xu6kvamy7q3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65wrsq5ye</guid>
      <category>หลามมันร้าย</category>
      
        <media:content url="https://image.nostr.build/8ccc372dad68a8f7a73365da8f1d181411919b41685cd8e1ff5b8072d062d565.jpg" medium="image"/>
        <enclosure 
          url="https://image.nostr.build/8ccc372dad68a8f7a73365da8f1d181411919b41685cd8e1ff5b8072d062d565.jpg" length="0" 
          type="image/jpeg" 
        />
      <noteId>naddr1qq2nset0v3xyxwtpv4e4gd2ewcu4xu6kvamy7q3qvm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqxpqqqp65wrsq5ye</noteId>
      <npub>npub1vm0kq43djwdd4psjgdjgn9z6fm836c35dv7eg7x74z3n3ueq83jqhkxp8e</npub>
      <dc:creator><![CDATA[123🦈ปลาฉลามขึ้นบก]]></dc:creator>
      <content:encoded><![CDATA[<p>แนวคิดอันนี้เกิดขึ้นหลังจากที่ผมได้รู้จัก LFS หรือ Log- structure File System มันทำให้ผมเกิดความคิดว่าในเมื่อมันสามารถที่จะเก็บ file และทุก log ของการเปลี่ยนแปลงในแต่ละไฟล์ งั้นแปลว่าในกรณีที่ file โดน encrypt มันก็น่าจะสามารถกู้คืนมาได้สิ เอ้ะแต่ถ้าเครื่องนั้นโดน ransomware ไปรอบนึงแล้วกู้คืนมาแล้วมันก็โดนอีกอยู่ดีมั้ย เลยเกิดไอเดียใหม่ว่าแล้วถ้าเราหา SSD อีกลูกมาเก็บ backup ถ้าโดน ransomware ก็ถอดไปเสียบเครื่องใหม่ก็จบ ตะตะแต่ว่า LFS เนี่ย ดั้นนนใช้ไม่ได้กับ windows หรือ Mac เอาละ ปัญหาใหม่มาอีกละ งั้นต้องทำไงล่ะ ? หึเก็บไว้บอกท้ายบทความละกัน มาทำความเข้าใจโปรเจคนี้กันทีละขั้นตอนกันดีกว่า</p>
<h2>Log-structure File System (LFS)</h2>
<p>เป็น File system รูปแบบหนึ่งที่จะทำการเก็บข้อมูลเป็น log และสามารถย้อนกลับได้ทุกการกระทำ นอกจากมีความถี่ในการสร้าง snapshot ที่สูงมาก จริง ๆ แล้วเหมาะกับงานประเภทที่ต้องการความต่อเนื่องหากดบัไปต้องกู้คืนได้มากที่สุดเท่าที่เป็นไปได้ แต่เพราะไอความสามารถตรงนั้นของมันนี่แหละ ที่ผมมองว่ามันน่าจะหยิบมาใช้กับการกู้คืน file หลังจากโดน ransomware ได้แน่ ๆ โดยในครั้งนี้ผมเลือกใช้เป็น NILFS2 เนื่องจากดูแล้วน่าจะเหลือตัวเดียวที่ยังพอมีการพัฒนาอยู่ 5555 รูปแบบการเก็บข้อมูลจะเหมือนกับภาพด้านล่างนี้ </p>
<p><img src="https://sarwiki.informatik.hu-berlin.de/images/a/a8/Lfs-layout-log.png" alt="image"></p>
<p>ตัวอย่าง:<br>เดิมที file A: "AAAAA" จากนั้นผมได้ทำการอัพเดตข้อมูลใน file A เป็น "BBBBB" ด้วยความสามารถของ LFS มันสามารถที่จะดึง file A เวอร์ชันที่เป็น "AAAAA" กลับมาได้</p>
<p>นี่เป็นปัจจัยสำคัญที่ทำให้ผมมองว่า LFS เหมาะสมที่จะมาเป็นระบบไฟล์ที่ใช้ในการสำรองข้อมูล แต่อยากที่ได้กล่าวไว้ข้างต้นว่าปัญหาของระบบไฟล์นี้คือมันใช้พื้นที่เก็บข้อมูลค่อนข้างสูง และมี write speed ที่ค่อนข้างช้า ถ้าเทียบกับระบบไฟล์อื่น ๆ ในกรณีที่ความเร็วของ SSD เท่ากัน เลยมองว่าถ้าจะใช้เป็นระบบหลักในการเก็บข้อมูลทุกอย่างคงจะไม่เหมาะ เลยนำไปสู่การทำระบบโดยใช้ระบบไฟล์สองแบบที่แตกต่างกัน</p>
<h2>System Design</h2>
<p>อย่างที่ได้พูดถึงข้อเสียของ NILFS2 ไปข้างต้น แปลว่าถ้าอยากจะให้คอมพิวเตอร์ทำงานได้อย่างมีประสิทธิภาพคงเดิมและสามารถป้องกัน ransomware ได้ด้วยก็จำเป็นต้องมีระบบไฟล์ที่ใช้กันทั่วไปอย่าง FAT32 หรือ ext4 และใช้ SSD อีกลูกหนึ่งที่ format เป็น NILFS2 และเขียนโปรแกรมให้คอยมอนิเตอร์ทุก ๆ กิจกรรมบน user space และทุกครั้งที่เกิดการเขียนไฟล์ขึ้นให้เขียนลงใน SSD ที่เป็น NILFS2 ด้วย ดังภาพที่แสดงด้านล่างนี้</p>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1722426766185-YAKIHONNES3.png" alt="image"></p>
<p>แล้วทำไมไฟล์ในลูกที่เก็บสำรองข้อมูลถึงไม่เท่ากับจำนวนไฟล์ในที่เก็บข้อมูลหลักล่ะ ? เนื่องด้วยความเร็วในการเขียนที่ค่อนข้างแตกต่างกันของทั้งสอง ผมเลยมองว่าถ้าเราเก็บในรูปแบบบล๊อกจะทำให้เก็บข้อมูลได้ไวกว่า อย่างตัวอย่างในรูป สมมุติว่าไฟล์ A มีขนาดประมาณ 3 บล๊อกใน SSD ที่เป็น nilfs2 ก็จะมี 3 ไฟล์และต้องใช้ทั้งสามไฟล์เพื่อที่จะคืนค่าไฟล์ A กลับมา ถ้าอ่านมาถึงตรงนี้อาจจะเกิดข้อสงสัยว่า แล้วจะทำให้มันยุ่งยากทำไม คัดลอกไฟล์มาใส่ก็จบแล้วมั้ย ? ก็ใช่แหละและจริง ๆ ผมคิดว่าทำแบบนั้นก็เพียงพอ แต่ว่าอย่างที่บอกไปข้างต้น ผมอยากได้ระบบที่ป้องกันได้ 100% ผมเลยเลือกที่จะมอนิเตอร์ kernel เอาไว้และเมื่อมีการเขียนไฟล์เกิดขึ้นผมต้องการดึงข้อมูลมาจากตรงนั้นเลย ไม่อยากรอถูกเขียนลงในพื้นที่เก็บข้อมูลหลักก่อนแล้วค่อยคัดลอกมา จริง ๆ ก็ด้วยเหตุผลด้านประสิทธิภาพด้วย </p>
<h2>แล้วจะมอนิเตอร์ kernel อย่างไร ??</h2>
<p>ในครั้งนี้ผมเลือกที่จะใช้เป็น eBPF (extended Berkeley Packet Filter) จริงแล้วเจ้า eBPF เนี่ยใช้งานได้หลากหลายเลยแหละ เรียกได้ว่าประโยชน์รอบด้านสุด ๆ ตามรูปที่แนบด้านล่างเลย</p>
<p><img src="https://ebpf.io/static/e293240ecccb9d506587571007c36739/ea28c/overview.webp" alt="image"></p>
<p>แต่ในครั้งนี้เราจะยุ่งกับมันเพียงแค่การใช้งานเพื่อสอดส่อง kernel เท่านั้น</p>
<p><img src="https://ebpf.io/static/99c69bbff092c35b9c83f00a80fed240/fb370/hook-overview.webp" alt="image"></p>
<p>ภาพด้านบนนี้แสดงให้เห็นจุดที่เราสามารถใช้ eBPF ในการดึงข้อมูลได้ นั่นเลยเป็นเหตุผลหลักที่ผมเลือกใช้ โดยวางการทำงานทั้งหมดของการมอนิเตอร์ไว้ดังนี้</p>
<ol>
<li>ใช้ eBPF เพื่อคอยเช็คว่ามีการเขียนเกิดขึ้นมั้ยโดยการอ่านค่า flag จาก NVMe ว่ามีค่าเป็นอะไรจากนั้นนำค่าที่ได้มา XOR ด้วย mask ถ้าค่าออกมาเป็น 1 แปลว่านั่นคือ write_operation (อาจแตกต่างกันแล้วแต่ version) </li>
<li>เมื่อเช็คค่าแล้วเป็น write_operation จากนั้นก็ให้ทำการอ่านเลข sector, และขนาดของข้อมูลที่ต้องการจะเขียน </li>
<li>จากนั้นเข้าไปอ่านต่อใน Bio ลงไปยัง Bio_vec และไป Bv_page ตามลำดับ เพื่ออ่านข้อมูลทั้งหมดที่มาจากคำสั่งในการเขียนครั้งนั้น ๆ<br> <img src="https://litux.nl/mirror/kerneldevelopment/0672327201/images/0672327201/graphics/13fig02.gif" alt="image"><br>*ภาพประกอบเพิ่มเติมเพื่อใครงงว่า Bio คืออะไรข้อมูลเวลาเราเขียนจะอยู่บน page</li>
<li>ส่งข้อมูลที่ได้ทั้งหมดออกมา</li>
</ol>
<p>เพียงเท่านี้เราก็ทำการดึงข้อมูลทุกครั้งที่เราเขียนได้แล้ว และจะนำมันเข้าสู่ขั้นตอนต่อไปในการเก็บข้อมูลลง SSD</p>
<h2>เก็บข้อมูลและส่งไป SSD ที่เป็น nilfs2</h2>
<p>เมื่อได้ข้อมูลมาจากการทำงานที่ได้กล่าวไว้ข้างบนแล้ว ก็จะได้ชุดข้อมูลมาชุดหนึ่ง ส่งออกมันมาจาก ebpf(C program) มาสู่ Python ต่อโดยมีขั้นตอนดังนี้</p>
<ol>
<li>นำเลข sector ที่ได้มาทำการคูณด้วยขนาดของ sector เพื่อให้เราได้ logical address มา จากนั้นให้นำ logical address หารด้วยขนาดของบล๊อกเพื่อให้ได้เลขบล๊อก</li>
<li>นำข้อมูลในแต่ละ sector มาเรียงลงในบล๊อกที่มันอยู่ละบันทึกลงไปใน SSD</li>
</ol>
<p>ตัวอย่างเพื่อให้เห็นภาพมากขึ้น<br>สมมุติว่าข้อมูลที่ส่งกลับมาขนาด 4097 B และเริ่มเขียนที่ sector 0<br>(กำหนดให้ 1 sector มีขนาด 512B และ 1 Block มี 8 sector)</p>
<p>4097/512 = 8.xx ก็แปลว่าข้อมูลนี้ต้องเก็บใน 9 sector คือ sector 0 ถึง 8<br>และ 8 sector รวมเป็น 1 block แปลว่าข้อมูลใน sector 0-7จะอยู่ใน block 0 และ sector 8 จะอยู่ใน block 1 แปลว่าโปรแกรมของผมจะสร้างมาสองไฟล์คือ 0,1 จากนั้นจะทำการเติม 0 ท้ายไฟล์ 1 จนมีขนาด 4096 B เท่ากับขนาดของ block</p>
<p>สำหรับคนที่งงว่า sector บล๊อกคืออะไร<br><img src="https://cstaleem.com/wp-content/uploads/2020/06/Hard-Disk-structure-in-OS.png" alt="image"></p>
<p>ให้ดูตรงรูปกลม ๆ ทางซ้ายมือจะเห็นได้ว่ามันเป็นหน่วยความจำในจานหมุน ซึ่ง sector คือหน่วยย่อยสุด และ sector รวม ๆ กันหลาย ๆ sector จะเป็น cluter บางที่ก็เรียก Tracks บางที่ก็ Block ซึ่งนี่แหละคือบล๊อกที่ผมหมายถึง</p>
<p>เพียงเท่านี้เราก็ได้ระบบที่สามารถป้องกัน ransomware ได้แล้ว เพราะเนื่องจากเมื่อเราโดน ransomware และไฟล์เราถูก encrypt เราก็เพียงใช้ความความสามารถของ SSD ลูกที่เป็น nilfs2 เพื่อนำไฟล์ดั้งเดิมก่อนจะถูก encrypt กับมาได้ดังรูปประกอบด้านล่างนี้</p>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1722431485024-YAKIHONNES3.png" alt="image"></p>
<h2>ส่งท้าย</h2>
<p>จริง ๆ แล้วที่ผมเก็บเป็นไฟล์ block เพราะผมอยากให้ backup file สามารถเข้ากันได้กับทุกระบบไฟล์เพื่อให้สามารถใช้งานได้กับทุกระบบ ถึงจะยังทำไม่ได้ก็เหอะ 55555 </p>
]]></content:encoded>
      <itunes:author><![CDATA[123🦈ปลาฉลามขึ้นบก]]></itunes:author>
      <itunes:summary><![CDATA[<p>แนวคิดอันนี้เกิดขึ้นหลังจากที่ผมได้รู้จัก LFS หรือ Log- structure File System มันทำให้ผมเกิดความคิดว่าในเมื่อมันสามารถที่จะเก็บ file และทุก log ของการเปลี่ยนแปลงในแต่ละไฟล์ งั้นแปลว่าในกรณีที่ file โดน encrypt มันก็น่าจะสามารถกู้คืนมาได้สิ เอ้ะแต่ถ้าเครื่องนั้นโดน ransomware ไปรอบนึงแล้วกู้คืนมาแล้วมันก็โดนอีกอยู่ดีมั้ย เลยเกิดไอเดียใหม่ว่าแล้วถ้าเราหา SSD อีกลูกมาเก็บ backup ถ้าโดน ransomware ก็ถอดไปเสียบเครื่องใหม่ก็จบ ตะตะแต่ว่า LFS เนี่ย ดั้นนนใช้ไม่ได้กับ windows หรือ Mac เอาละ ปัญหาใหม่มาอีกละ งั้นต้องทำไงล่ะ ? หึเก็บไว้บอกท้ายบทความละกัน มาทำความเข้าใจโปรเจคนี้กันทีละขั้นตอนกันดีกว่า</p>
<h2>Log-structure File System (LFS)</h2>
<p>เป็น File system รูปแบบหนึ่งที่จะทำการเก็บข้อมูลเป็น log และสามารถย้อนกลับได้ทุกการกระทำ นอกจากมีความถี่ในการสร้าง snapshot ที่สูงมาก จริง ๆ แล้วเหมาะกับงานประเภทที่ต้องการความต่อเนื่องหากดบัไปต้องกู้คืนได้มากที่สุดเท่าที่เป็นไปได้ แต่เพราะไอความสามารถตรงนั้นของมันนี่แหละ ที่ผมมองว่ามันน่าจะหยิบมาใช้กับการกู้คืน file หลังจากโดน ransomware ได้แน่ ๆ โดยในครั้งนี้ผมเลือกใช้เป็น NILFS2 เนื่องจากดูแล้วน่าจะเหลือตัวเดียวที่ยังพอมีการพัฒนาอยู่ 5555 รูปแบบการเก็บข้อมูลจะเหมือนกับภาพด้านล่างนี้ </p>
<p><img src="https://sarwiki.informatik.hu-berlin.de/images/a/a8/Lfs-layout-log.png" alt="image"></p>
<p>ตัวอย่าง:<br>เดิมที file A: "AAAAA" จากนั้นผมได้ทำการอัพเดตข้อมูลใน file A เป็น "BBBBB" ด้วยความสามารถของ LFS มันสามารถที่จะดึง file A เวอร์ชันที่เป็น "AAAAA" กลับมาได้</p>
<p>นี่เป็นปัจจัยสำคัญที่ทำให้ผมมองว่า LFS เหมาะสมที่จะมาเป็นระบบไฟล์ที่ใช้ในการสำรองข้อมูล แต่อยากที่ได้กล่าวไว้ข้างต้นว่าปัญหาของระบบไฟล์นี้คือมันใช้พื้นที่เก็บข้อมูลค่อนข้างสูง และมี write speed ที่ค่อนข้างช้า ถ้าเทียบกับระบบไฟล์อื่น ๆ ในกรณีที่ความเร็วของ SSD เท่ากัน เลยมองว่าถ้าจะใช้เป็นระบบหลักในการเก็บข้อมูลทุกอย่างคงจะไม่เหมาะ เลยนำไปสู่การทำระบบโดยใช้ระบบไฟล์สองแบบที่แตกต่างกัน</p>
<h2>System Design</h2>
<p>อย่างที่ได้พูดถึงข้อเสียของ NILFS2 ไปข้างต้น แปลว่าถ้าอยากจะให้คอมพิวเตอร์ทำงานได้อย่างมีประสิทธิภาพคงเดิมและสามารถป้องกัน ransomware ได้ด้วยก็จำเป็นต้องมีระบบไฟล์ที่ใช้กันทั่วไปอย่าง FAT32 หรือ ext4 และใช้ SSD อีกลูกหนึ่งที่ format เป็น NILFS2 และเขียนโปรแกรมให้คอยมอนิเตอร์ทุก ๆ กิจกรรมบน user space และทุกครั้งที่เกิดการเขียนไฟล์ขึ้นให้เขียนลงใน SSD ที่เป็น NILFS2 ด้วย ดังภาพที่แสดงด้านล่างนี้</p>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1722426766185-YAKIHONNES3.png" alt="image"></p>
<p>แล้วทำไมไฟล์ในลูกที่เก็บสำรองข้อมูลถึงไม่เท่ากับจำนวนไฟล์ในที่เก็บข้อมูลหลักล่ะ ? เนื่องด้วยความเร็วในการเขียนที่ค่อนข้างแตกต่างกันของทั้งสอง ผมเลยมองว่าถ้าเราเก็บในรูปแบบบล๊อกจะทำให้เก็บข้อมูลได้ไวกว่า อย่างตัวอย่างในรูป สมมุติว่าไฟล์ A มีขนาดประมาณ 3 บล๊อกใน SSD ที่เป็น nilfs2 ก็จะมี 3 ไฟล์และต้องใช้ทั้งสามไฟล์เพื่อที่จะคืนค่าไฟล์ A กลับมา ถ้าอ่านมาถึงตรงนี้อาจจะเกิดข้อสงสัยว่า แล้วจะทำให้มันยุ่งยากทำไม คัดลอกไฟล์มาใส่ก็จบแล้วมั้ย ? ก็ใช่แหละและจริง ๆ ผมคิดว่าทำแบบนั้นก็เพียงพอ แต่ว่าอย่างที่บอกไปข้างต้น ผมอยากได้ระบบที่ป้องกันได้ 100% ผมเลยเลือกที่จะมอนิเตอร์ kernel เอาไว้และเมื่อมีการเขียนไฟล์เกิดขึ้นผมต้องการดึงข้อมูลมาจากตรงนั้นเลย ไม่อยากรอถูกเขียนลงในพื้นที่เก็บข้อมูลหลักก่อนแล้วค่อยคัดลอกมา จริง ๆ ก็ด้วยเหตุผลด้านประสิทธิภาพด้วย </p>
<h2>แล้วจะมอนิเตอร์ kernel อย่างไร ??</h2>
<p>ในครั้งนี้ผมเลือกที่จะใช้เป็น eBPF (extended Berkeley Packet Filter) จริงแล้วเจ้า eBPF เนี่ยใช้งานได้หลากหลายเลยแหละ เรียกได้ว่าประโยชน์รอบด้านสุด ๆ ตามรูปที่แนบด้านล่างเลย</p>
<p><img src="https://ebpf.io/static/e293240ecccb9d506587571007c36739/ea28c/overview.webp" alt="image"></p>
<p>แต่ในครั้งนี้เราจะยุ่งกับมันเพียงแค่การใช้งานเพื่อสอดส่อง kernel เท่านั้น</p>
<p><img src="https://ebpf.io/static/99c69bbff092c35b9c83f00a80fed240/fb370/hook-overview.webp" alt="image"></p>
<p>ภาพด้านบนนี้แสดงให้เห็นจุดที่เราสามารถใช้ eBPF ในการดึงข้อมูลได้ นั่นเลยเป็นเหตุผลหลักที่ผมเลือกใช้ โดยวางการทำงานทั้งหมดของการมอนิเตอร์ไว้ดังนี้</p>
<ol>
<li>ใช้ eBPF เพื่อคอยเช็คว่ามีการเขียนเกิดขึ้นมั้ยโดยการอ่านค่า flag จาก NVMe ว่ามีค่าเป็นอะไรจากนั้นนำค่าที่ได้มา XOR ด้วย mask ถ้าค่าออกมาเป็น 1 แปลว่านั่นคือ write_operation (อาจแตกต่างกันแล้วแต่ version) </li>
<li>เมื่อเช็คค่าแล้วเป็น write_operation จากนั้นก็ให้ทำการอ่านเลข sector, และขนาดของข้อมูลที่ต้องการจะเขียน </li>
<li>จากนั้นเข้าไปอ่านต่อใน Bio ลงไปยัง Bio_vec และไป Bv_page ตามลำดับ เพื่ออ่านข้อมูลทั้งหมดที่มาจากคำสั่งในการเขียนครั้งนั้น ๆ<br> <img src="https://litux.nl/mirror/kerneldevelopment/0672327201/images/0672327201/graphics/13fig02.gif" alt="image"><br>*ภาพประกอบเพิ่มเติมเพื่อใครงงว่า Bio คืออะไรข้อมูลเวลาเราเขียนจะอยู่บน page</li>
<li>ส่งข้อมูลที่ได้ทั้งหมดออกมา</li>
</ol>
<p>เพียงเท่านี้เราก็ทำการดึงข้อมูลทุกครั้งที่เราเขียนได้แล้ว และจะนำมันเข้าสู่ขั้นตอนต่อไปในการเก็บข้อมูลลง SSD</p>
<h2>เก็บข้อมูลและส่งไป SSD ที่เป็น nilfs2</h2>
<p>เมื่อได้ข้อมูลมาจากการทำงานที่ได้กล่าวไว้ข้างบนแล้ว ก็จะได้ชุดข้อมูลมาชุดหนึ่ง ส่งออกมันมาจาก ebpf(C program) มาสู่ Python ต่อโดยมีขั้นตอนดังนี้</p>
<ol>
<li>นำเลข sector ที่ได้มาทำการคูณด้วยขนาดของ sector เพื่อให้เราได้ logical address มา จากนั้นให้นำ logical address หารด้วยขนาดของบล๊อกเพื่อให้ได้เลขบล๊อก</li>
<li>นำข้อมูลในแต่ละ sector มาเรียงลงในบล๊อกที่มันอยู่ละบันทึกลงไปใน SSD</li>
</ol>
<p>ตัวอย่างเพื่อให้เห็นภาพมากขึ้น<br>สมมุติว่าข้อมูลที่ส่งกลับมาขนาด 4097 B และเริ่มเขียนที่ sector 0<br>(กำหนดให้ 1 sector มีขนาด 512B และ 1 Block มี 8 sector)</p>
<p>4097/512 = 8.xx ก็แปลว่าข้อมูลนี้ต้องเก็บใน 9 sector คือ sector 0 ถึง 8<br>และ 8 sector รวมเป็น 1 block แปลว่าข้อมูลใน sector 0-7จะอยู่ใน block 0 และ sector 8 จะอยู่ใน block 1 แปลว่าโปรแกรมของผมจะสร้างมาสองไฟล์คือ 0,1 จากนั้นจะทำการเติม 0 ท้ายไฟล์ 1 จนมีขนาด 4096 B เท่ากับขนาดของ block</p>
<p>สำหรับคนที่งงว่า sector บล๊อกคืออะไร<br><img src="https://cstaleem.com/wp-content/uploads/2020/06/Hard-Disk-structure-in-OS.png" alt="image"></p>
<p>ให้ดูตรงรูปกลม ๆ ทางซ้ายมือจะเห็นได้ว่ามันเป็นหน่วยความจำในจานหมุน ซึ่ง sector คือหน่วยย่อยสุด และ sector รวม ๆ กันหลาย ๆ sector จะเป็น cluter บางที่ก็เรียก Tracks บางที่ก็ Block ซึ่งนี่แหละคือบล๊อกที่ผมหมายถึง</p>
<p>เพียงเท่านี้เราก็ได้ระบบที่สามารถป้องกัน ransomware ได้แล้ว เพราะเนื่องจากเมื่อเราโดน ransomware และไฟล์เราถูก encrypt เราก็เพียงใช้ความความสามารถของ SSD ลูกที่เป็น nilfs2 เพื่อนำไฟล์ดั้งเดิมก่อนจะถูก encrypt กับมาได้ดังรูปประกอบด้านล่างนี้</p>
<p><img src="https://yakihonne.s3.ap-east-1.amazonaws.com/66df60562d939ada8612436489945a4ecf1d62346b3d9478dea8a338f3203c64/files/1722431485024-YAKIHONNES3.png" alt="image"></p>
<h2>ส่งท้าย</h2>
<p>จริง ๆ แล้วที่ผมเก็บเป็นไฟล์ block เพราะผมอยากให้ backup file สามารถเข้ากันได้กับทุกระบบไฟล์เพื่อให้สามารถใช้งานได้กับทุกระบบ ถึงจะยังทำไม่ได้ก็เหอะ 55555 </p>
]]></itunes:summary>
      <itunes:image href="https://image.nostr.build/8ccc372dad68a8f7a73365da8f1d181411919b41685cd8e1ff5b8072d062d565.jpg"/>
      </item>
      
      </channel>
      </rss>
    