خلاصهی کتاب
معرفی کتاب
Mastering Bitcoin: Programming the Open Blockchain کتابی است از آندریاس م. آنتونوپولوس (Andreas M. Antonopoulos) که انتشارات O’Reilly آن را منتشر کرده است؛ همان نویسندهای که بعدها Mastering Ethereum را هم نوشت. این کتاب مرجع فنیِ آشنا و پرارجاع بیتکوین است: از کلید خصوصی، آدرس و کیف پول شروع میکند، به ساختار تراکنش و زبان اسکریپت میرسد و بعد شبکهی همتابههمتا، بلاکچین، استخراج، اجماع و امنیت را توضیح میدهد. فصل آخر هم بلاکچین بیتکوین را بهعنوان بستر ساخت برنامهها بررسی میکند، از جمله کانالهای پرداخت و شبکهی Lightning.
مخاطب اصلی کتاب برنامهنویسهاست، ولی چند فصل ابتدایی (مقدمه و «بیتکوین چگونه کار میکند») برای هر کسی که میخواهد سازوکار درونی بیتکوین را بفهمد قابلخواندن است. بخش کلیدها، آدرسها، کیف پولها و امنیت هم برای کاربرِ عادی مفید است، چون توضیح میدهد «مالکیت» در بیتکوین دقیقاً یعنی چه.
چاپها و دسترسی
- ویرایش دوم (۲۰۱۷): خلاصهی این صفحه بر پایهی همین ویرایش نوشته شده است.
- ویرایش سوم (دسامبر ۲۰۲۳): با همکاری دیوید هاردینگ (David A. Harding) نوشته شده و رویدادهای پس از ۲۰۱۷، از جمله تاپروت، را هم پوشش میدهد. نسخهی کاغذی آن در آمازون فروخته میشود.
- متن کامل و رایگان: هر سه چاپ کتاب با مجوز آزاد Creative Commons Attribution-ShareAlike 4.0 در مخزن عمومی github.com/bitcoinbook/bitcoinbook در دسترساند و ویرایش سوم را میتوان آنلاین خواند. دکمهی همین صفحه به همین متن میرود.
پیش از خواندن: این صفحه ترجمهی کتاب نیست؛ خلاصهای مستقل و مفصل به زبان فارسی است و جای متن اصلی را نمیگیرد. چون بر پایهی ویرایش دوم (۲۰۱۷) است، بعضی بخشها با وضعیت امروز فرق دارند: سگویت در آن زمان تازه فعال شده بود، تاپروت هنوز وجود نداشت و پیوستهای مربوط به ابزارها (Bitcore، pycoin و Bitcoin Explorer) وضعیت همان سال را نشان میدهند. برای جزئیات دقیق، کدها و وضعیت روز، سراغ ویرایش سوم یا مستندات رسمی Bitcoin Core بروید.
این خلاصه به چه درسهایی کمک میکند؟
فصلهای مقدمه، سازوکار بیتکوین، کلیدها و آدرسها و کیف پولها به مباحث دورههای «معرفی بلاکچین و رمزارز» (G1) و «بیتکوین» (G2) نزدیکاند؛ فصل امنیت و بحث نگهداری کلید به دورهی «کاربر امن کریپتو» (G4). فصلهای تراکنش، اسکریپت و اجماع هم پایهی مناسبی برای فهمیدن تفاوت مدل UTXO بیتکوین با مدل حساب در اتریوماند.
فهرست خلاصهی فصلها
- پیشگفتار
- فصل ۱ — مقدمه (Introduction)
- فصل ۲ — بیتکوین چگونه کار میکند (How Bitcoin Works)
- فصل ۳ — بیتکوین کور: پیادهسازی مرجع (Bitcoin Core: The Reference Implementation)
- فصل ۴ — کلیدها و آدرسها (Keys, Addresses)
- فصل ۵ — کیفپولها (Wallets)
- فصل ۶ — تراکنشها (Transactions)
- فصل ۷ — تراکنشهای پیشرفته و اسکریپتنویسی (Advanced Transactions and Scripting)
- فصل ۸ — شبکهٔ بیتکوین (The Bitcoin Network)
- فصل ۹ — بلاکچین (The Blockchain)
- فصل ۱۰ — استخراج و اجماع (Mining and Consensus)
- فصل ۱۱ — امنیت بیتکوین (Bitcoin Security)
- فصل ۱۲ — کاربردهای بلاکچین (Blockchain Applications)
- پیوست A — وایتپیپر بیتکوین (The Bitcoin Whitepaper by Satoshi Nakamoto)
- پیوست B — عملگرها، ثابتها و نمادهای زبان اسکریپت تراکنش (Transaction Script Language Operators, Constants, and Symbols)
- پیوست C — پیشنهادهای بهبود بیتکوین (Bitcoin Improvement Proposals)
- پیوست D — شاهد جداشده (سگویت) (Segregated Witness)
- پیوست E — Bitcore
- پیوست F — pycoin، ku و tx
- پیوست G — دستورات Bitcoin Explorer (bx)
پیشگفتار
نوشتن «کتاب بیتکوین»
- نویسنده در اواسط ۲۰۱۱ برای نخستین بار به بیتکوین برخورد کرد و واکنش اولش بیاعتنایی بود («پول آدمهای نرد»). او میگوید این واکنش را در بسیاری از باهوشترین آشنایانش هم دیده است.
- بار دوم، در یک بحث فهرست پستی، سراغ مقالهٔ نهصفحهای ساتوشی ناکاموتو (Satoshi Nakamoto) رفت. پس از خواندن آن به این نتیجه رسید که بیتکوین صرفاً پول دیجیتال نیست، بلکه یک شبکهٔ اعتماد غیرمتمرکز است که میتواند پایهٔ کاربردهایی فراتر از ارز باشد.
- این درک او را وارد یک دورهٔ چهارماههٔ غرقشدن کامل کرد: روزی ۱۲ ساعت یا بیشتر خواندن، نوشتن و برنامهنویسی، تا جایی که بیش از ۲۰ پوند وزن کم کرد و تصمیم گرفت زندگی حرفهایاش را به بیتکوین اختصاص دهد.
- دو سال بعد، پس از ساخت چند استارتاپ کوچک پیرامون خدمات بیتکوینی، تصمیم گرفت نخستین کتابش را بنویسد تا شور خود را با مخاطبان گستردهتری در میان بگذارد؛ بیتکوین را هیجانانگیزترین فناوری پس از اینترنت میدانست.
مخاطب کتاب
- مخاطب اصلی برنامهنویسان هستند: کسانی که با یک زبان برنامهنویسی کار میکنند و میخواهند بفهمند ارزهای رمزنگاریشده چگونه کار میکنند، چگونه استفاده میشوند و چگونه میتوان نرمافزار مرتبط با آنها نوشت.
- چند فصل ابتدایی برای غیربرنامهنویسها هم بهعنوان مقدمهای عمیق بر سازوکار درونی بیتکوین و ارزهای رمزنگاریشده مناسب است.
چرا روی جلد حشره هست؟
- حشرهٔ روی جلد مورچهٔ برگبر (leafcutter ant) است. این مورچهها برگ نمیخورند؛ از برگ برای پرورش قارچ استفاده میکنند که غذای اصلی کلنی است، یعنی عملاً «کشاورزی» میکنند.
- کلنی آنها یکی از بزرگترین و پیچیدهترین جوامع جانوری است، با اینکه رتبهبندی طبقاتی و ملکه (برای تولید مثل) دارد اما هیچ مرجع یا رهبر مرکزی ندارد. هر مورچه فقط از چند قاعدهٔ ساده پیروی میکند و از راه تعامل اجتماعی و تبادل مواد شیمیایی (فرومون) با دیگران هماهنگ میشود؛ رفتار هوشمند کل کلنی یک خاصیت برآمده (emergent) از این تعاملهاست.
- تشبیه نویسنده: بیتکوین هم شبکهٔ اعتماد غیرمتمرکز پیچیدهای است که هر گره در آن چند قاعدهٔ ریاضی ساده را دنبال میکند. پیچیدگی و اعتماد از هیچ گرهٔ منفرد نمیآید، از تعامل بسیاری از گرهها میآید؛ مانند کلنی مورچهها که بدون هماهنگی مرکزی کارهای شگفتانگیز میکند.
قراردادهای نگارشی
- حروف ایتالیک برای اصطلاحات جدید، نشانیهای اینترنتی، ایمیل، نام فایل و پسوندها؛ قلم همعرض (constant width) برای فهرست کد و نام متغیر/تابع/دستور؛ همعرض پررنگ برای دستوری که کاربر باید دقیقاً تایپ کند؛ همعرض ایتالیک برای مقادیری که باید با مقدار خود کاربر یا بافت جایگزین شوند.
- سه آیکون در متن هست: نکته (TIP)، یادداشت (NOTE) و هشدار (WARNING).
نمونهکدها
- مثالها به Python، C++ و خط فرمان سیستمهای یونیکسمانند (لینوکس و macOS) نوشته شدهاند و همگی در مخزن گیتهاب کتاب، زیرپوشهٔ
code، در دسترساند. میتوان کد را fork کرد، آزمود یا اصلاحیه فرستاد. - با نصب حداقلی مفسر/کامپایلر در اغلب سیستمعاملها قابل اجراست و در جاهای لازم دستور نصب و خروجی گامبهگام آمده است.
- برخی خطوط برای چاپ شکسته شدهاند (با بکاسلش و خط جدید)؛ هنگام تایپ مجدد باید این دو نویسه حذف و خطوط به هم وصل شوند.
- مقادیر واقعیاند: کلیدهای خصوصی، کلیدهای عمومی و آدرسها حقیقیاند و تراکنشها، بلاکها و ارجاعات بلاکچین واقعاً در بلاکچین بیتکوین ثبت شدهاند؛ پس میتوان نتیجهٔ محاسبات را روی هر سامانهٔ بیتکوینی راستیآزمایی کرد.
مجوز استفاده از کد
- نمونهکدها را بهطور معمول میتوان در برنامهها و مستندات خود به کار برد؛ فقط بازتولید بخش قابلتوجهی از کد نیاز به اجازه دارد (مثلاً فروش یا توزیع CD نمونهها از کتابهای اُرایلی، یا گنجاندن حجم زیادی از کد در مستندات محصول). نقل مثال در پاسخ به یک پرسش نیاز به اجازه ندارد.
- ذکر منبع (عنوان، نویسنده، ناشر، ISBN) مطلوب ولی اجباری نیست.
- برخی نسخههای کتاب با مجوز متنباز مانند CC-BY-NC عرضه میشوند و در آن صورت شرایط همان مجوز اعمال میشود. برای موارد خارج از «استفادهٔ منصفانه» میتوان با ناشر ([email protected]) تماس گرفت.
آدرسها و تراکنشهای کتاب
- آدرسها، تراکنشها، کلیدها، کدهای QR و دادههای بلاکچین موجود در کتاب بیشتر واقعی هستند؛ میتوان بلاکچین را مرور کرد، تراکنشهای نمونه را دید و با اسکریپت خودتان واکشی کرد.
- اما کلیدهای خصوصی سازندهٔ این آدرسها یا در کتاب چاپ شدهاند یا «سوزانده» شدهاند. بنابراین هر پولی به آنها بفرستید یا برای همیشه از دست میرود یا هر خوانندهٔ کتاب میتواند آن را بردارد. به هیچیک از آدرسهای کتاب پول نفرستید.
سایر بخشهای ابتدای کتاب
- O’Reilly Safari: معرفی پلتفرم اشتراکی آموزش و مرجع ناشر (کتاب، ویدیو و مسیر یادگیری از صدها ناشر).
- تماس: نشانی ناشر و ایمیل بازخورد فنی؛ نویسنده از طریق وبسایت شخصی، https://bitcoinbook.info/ (برای نسخهٔ باز و ترجمهها) و شبکههای اجتماعی در دسترس است. او از حامیان ماهانهاش در Patreon نیز تشکر کرده است.
قدردانیها
- نویسنده کتاب را حاصل جامعهٔ بیتکوین میداند؛ تفکیک فناوری از جامعه ممکن نیست و هر ایده، تشبیه، پرسش و پاسخی که در کتاب هست در تعامل با این جامعه الهام گرفته، آزموده یا بهبود یافته است.
- او از معلم نگارش انگلیسیاش، همکاران دوران ستوننویسی در مجلهٔ Network World، حامیان طرح پیشنهادی کتاب و ویراستاران اُرایلی (برای ویراست دوم: Timothy McGovern، Kim Cofer و Rebecca Panzer برای نمودارهای جدید) تشکر میکند.
- یک نقطهٔ عطف نگارشی: پیشنویس اولیهٔ فصلها دشوار بود چون بیتکوین موضوعی درهمتنیده است (کشیدن یک نخ، کل بافت را میکشد). راهحل او روایت بیتکوین از دل داستان آدمهایی بود که از آن استفاده میکنند، و این کار نوشتن را بسیار آسان کرد.
- پیشنویسها در گیتهاب منتشر شد و بیش از صد نظر و اصلاح دریافت کرد؛ ویراستاران داوطلب (Ming T. Nguyen برای ویراست اول، Will Binns برای ویراست دوم) پلریکوئستها را مدیریت کردند. فهرست مشارکتکنندگان گیتهاب در پایان بخش آمده است.
- چند توسعهدهندهٔ بیتکوین کد، بازبینی و نظر دادند؛ از جمله در ویراست دوم توسعهدهندگان Bitcoin Core دربارهٔ سگویت (SegWit) و فصل تراکنشها، و پدیدآورندگان شبکهٔ لایتنینگ (Lightning Network) که مفاهیم آن را توضیح دادند.
- در پایان از مادر (که او را با کتاب بزرگ کرد و نخستین رایانهاش را در ۱۹۸۲ خرید) و پدرش (مهندس عمران که تفکر منطقی و عشق به علم را به او آموخت) سپاسگزاری شده است.
جمعبندی
پیشگفتار چارچوب ذهنی کتاب را میسازد: برنامهنویسان مخاطب اصلیاند و فصلهای نخست برای عموم هم قابل فهم است؛ بیتکوین مانند کلنی مورچهها سامانهای غیرمتمرکز است که از قواعد ساده و تعامل گرهها اعتماد میسازد؛ نمونهها واقعیاند اما هرگز نباید به آدرسهای کتاب پول فرستاد؛ و کتاب با روایت داستان کاربران (آلیس، باب، جینگ و دیگران) پیش میرود.
فصل ۱ — مقدمه (Introduction)
بیتکوین چیست؟
- بیتکوین (bitcoin) مجموعهای از مفاهیم و فناوریهاست که زیربنای یک اکوسیستم پول دیجیتال را میسازد. واحد پولی به نام بیتکوین برای ذخیره و انتقال ارزش میان شرکتکنندگان شبکه به کار میرود. کاربران از طریق پروتکل بیتکوین (عمدتاً روی اینترنت) با هم ارتباط میگیرند؛ پشتهٔ پروتکل متنباز است و روی لپتاپ تا گوشی هوشمند اجرا میشود.
- با بیتکوین تقریباً هر کاری که با پول رایج میشود انجام داد: خرید و فروش کالا، فرستادن پول به افراد یا سازمانها، اعطای اعتبار. میتوان آن را در صرافیهای تخصصی خرید، فروخت و با ارزهای دیگر مبادله کرد. نویسنده آن را «شکل کامل پول برای اینترنت» مینامد: سریع، امن و بدون مرز.
- بر خلاف پول سنتی، بیتکوین کاملاً مجازی است: نه سکهٔ فیزیکی دارد و نه حتی «سکهٔ دیجیتال» به معنای دقیق؛ سکهها در تراکنشهایی مستتر هستند که ارزش را از فرستنده به گیرنده منتقل میکنند. کاربر کلیدهایی دارد که مالکیت را در شبکه اثبات میکند و با آنها تراکنش را امضا میکند تا ارزش را آزاد و به مالک جدید منتقل کند. کلیدها معمولاً در کیف پول دیجیتال روی رایانه یا گوشی نگهداری میشوند. تنها پیشنیاز خرجکردن، در اختیار داشتن کلیدی است که بتواند تراکنش را امضا کند؛ یعنی کنترل کاملاً در دست کاربر است.
- بیتکوین سامانهای توزیعشده و همتابههمتا (peer-to-peer) است و هیچ سرور یا نقطهٔ کنترل مرکزی ندارد. بیتکوین جدید از راه استخراج (mining) پدید میآید: رقابت برای یافتن جواب یک مسئلهٔ ریاضی همزمان با پردازش تراکنشها. هر شرکتکنندهٔ شبکه که پشتهٔ کامل پروتکل را اجرا کند میتواند ماینر باشد. بهطور میانگین هر ۱۰ دقیقه یک نفر تراکنشهای ۱۰ دقیقهٔ گذشته را تأیید میکند و با بیتکوین تازهساخته پاداش میگیرد. به بیان نویسنده، استخراج کارکردهای انتشار پول و تسویهحساب بانک مرکزی را غیرمتمرکز میکند و جای بانک مرکزی را میگیرد.
قواعد تنظیمکنندهٔ شبکه
- سختی (difficulty) مسئلهٔ استخراج بهطور پویا تنظیم میشود تا صرفنظر از تعداد ماینرها و توان پردازشی آنها، بهطور میانگین هر ۱۰ دقیقه یک جواب پیدا شود.
- نرخ ساخت بیتکوین جدید هر ۴ سال نصف میشود (halving) و مجموع بیتکوینهای قابل ساخت به عددی اندکی کمتر از ۲۱ میلیون محدود است. منحنی عرضه قابل پیشبینی است و حدود سال ۲۱۴۰ به ۲۱ میلیون میرسد. بهدلیل کاهش نرخ انتشار، در بلندمدت بیتکوین تورمزدا (deflationary) است و نمیتوان با «چاپ پول» بیش از برنامهٔ تعیینشده آن را متورم کرد.
چهار نوآوری کلیدی
بیتکوین فقط یک ارز نیست؛ نام پروتکل، شبکهٔ همتابههمتا و یک نوآوری در محاسبات توزیعشده است و ارز تنها نخستین کاربرد آن. چهار جزء که در ترکیبی منحصربهفرد کنار هم آمدهاند:
| جزء | توضیح |
|---|---|
| شبکهٔ همتابههمتای غیرمتمرکز | پروتکل بیتکوین |
| دفتر کل عمومی تراکنشها | بلاکچین (blockchain) |
| قواعد اعتبارسنجی مستقل تراکنش و انتشار ارز | قواعد اجماع (consensus rules) |
| سازوکار رسیدن به اجماع سراسری غیرمتمرکز روی بلاکچین معتبر | الگوریتم اثبات کار (Proof-of-Work) |
نویسنده بیتکوین را «اینترنت پول» میداند: شبکهای برای انتشار ارزش و تضمین مالکیت داراییهای دیجیتال از طریق محاسبات توزیعشده.
کادر: ارزهای دیجیتال پیش از بیتکوین
- ظهور پول دیجیتال کارآمد به پیشرفت رمزنگاری گره خورده است. سه پرسش بنیادین هر پذیرندهٔ پول دیجیتال:
- آیا اصیل است و جعلی نیست؟
- آیا فقط یک بار قابل خرج است؟ (مسئلهٔ پرداخت دوبارهخرج / double spending)
- آیا مطمئنم کسی دیگر نمیتواند ادعا کند این پول مال اوست؟
- اسکناس کاغذی با کاغذ و چاپ پیچیده با جعل مبارزه میکند و مسئلهٔ دوبارخرج را ذاتاً ندارد (یک اسکناس همزمان در دو جا نیست). در پول الکترونیک رایج، جعل و دوبارخرج با تسویهٔ همهٔ تراکنشها از طریق مراجع مرکزی که دید سراسری دارند حل میشود. در پول دیجیتال، امضای دیجیتال (رمزنگاری) مشروعیت ادعای مالکیت را اثبات میکند و با معماری مناسب میتواند مشکل دوبارخرج را هم حل کند.
- از اواخر دهه ۱۹۸۰ که رمزنگاری گسترش یافت، پژوهشگران کوشیدند ارز دیجیتال بسازند؛ این پروژهها معمولاً ارز را به پول ملی یا فلز گرانبها (مثل طلا) وابسته میکردند. اما متمرکز بودند: یک اتاق پایاپای (clearinghouse) تراکنشها را در فواصل منظم تسویه میکرد. بنابراین هدف آسانی برای دولتها و هکرها بودند؛ بسیاری از آنها از راه پیگرد قانونی از میان رفتند و برخی با تعطیلی ناگهانی شرکت مادر به سقوط رسیدند. در برابر دخالت مخالفان (مشروع یا مجرم) به یک ارز دیجیتال غیرمتمرکز نیاز بود تا نقطهٔ واحد حمله نداشته باشد؛ بیتکوین چنین سامانهای است.
تاریخچهٔ بیتکوین
- بیتکوین در ۲۰۰۸ با انتشار مقالهٔ «Bitcoin: A Peer-to-Peer Electronic Cash System» با نام مستعار ساتوشی ناکاموتو معرفی شد (بیشتر در پیوست A). ناکاموتو چند ابداع قبلی مانند b-money و HashCash را ترکیب کرد تا نظام پول الکترونیکی کاملاً غیرمتمرکزی بسازد که برای انتشار پول، تسویه و اعتبارسنجی به مرجع مرکزی نیاز نداشته باشد.
- نوآوری کلیدی: استفاده از یک سامانهٔ محاسبات توزیعشده (الگوریتم اثبات کار) برای برگزاری یک «انتخابات» سراسری هر ۱۰ دقیقه، تا شبکهٔ غیرمتمرکز دربارهٔ وضعیت تراکنشها به اجماع برسد. این راهحل شیوهٔ سنتی (تسویه از طریق اتاق پایاپای مرکزی) برای مسئلهٔ دوبارخرج را کنار میگذارد.
- شبکه در ۲۰۰۹ بر پایهٔ پیادهسازی مرجع ناکاموتو راه افتاد و بعدها برنامهنویسان بسیاری آن را بازبینی کردند. توان اثبات کار بهصورت نمایی رشد کرد و از مجموع توان پردازشی برترین ابررایانههای جهان فراتر رفته است. ارزش کل بازار بیتکوین گاه از ۲۰ میلیارد دلار گذشته و بزرگترین تراکنش تاکنون ۱۵۰ میلیون دلار بوده که آنی و بدون کارمزد پردازش شد (طبق آمار زمان نگارش).
- ناکاموتو در آوریل ۲۰۱۱ از صحنهٔ عمومی کنار رفت و توسعهٔ کد و شبکه را به جمعی از داوطلبان سپرد. هویت فرد یا افراد پشت بیتکوین هنوز ناشناخته است. با این حال هیچکس (از جمله ناکاموتو) کنترل فردی بر سامانه ندارد؛ بیتکوین بر اصول ریاضی شفاف، کد متنباز و اجماع شرکتکنندگان اجرا میشود. این ابداع شاخههای علمی جدیدی در محاسبات توزیعشده، اقتصاد و اقتصادسنجی پدید آورده است.
کادر: راهحلی برای یک مسئلهٔ محاسبات توزیعشده
راهحل ناکاموتو پاسخی عملی و نو به مسئلهٔ ژنرالهای بیزانسی (Byzantine Generals’ Problem) است: توافق بر سر یک اقدام یا وضعیت سیستم با تبادل اطلاعات روی شبکهای ناامن و احتمالاً آلوده. استفاده از اثبات کار برای رسیدن به اجماع بدون مرجع مورد اعتماد، گامی بزرگ در محاسبات توزیعشده است و کاربردهایی فراتر از ارز دارد: اثبات انصاف انتخابات، قرعهکشی، ثبت دارایی، سندرسمیکردن دیجیتال (notarization) و غیره.
کاربردها، کاربران و داستانهایشان
پول فناوری باستانی تسهیل مبادلهٔ ارزش میان آدمهاست؛ پس نویسنده بیتکوین را از دید کاربرانش میبیند. هر داستان یک یا چند مورد استفاده را نشان میدهد و در کل کتاب پی گرفته میشود:
| شخصیت | مورد استفاده | آنچه مطرح میشود |
|---|---|---|
| آلیس (Alice)، خلیج سانفرانسیسکو | خردهفروشی کمارزش در آمریکای شمالی | با بیتکوین آشنا میشود، مقداری میخرد و در کافهٔ باب (پالو آلتو) یک فنجان قهوه میخرد؛ نرمافزار، صرافیها و تراکنش پایه از دید مصرفکننده |
| کارول (Carol)، صاحب گالری هنری سانفرانسیسکو | خردهفروشی پرارزش | تابلوهای گران را با بیتکوین میفروشد؛ مخاطرهٔ حملهٔ اجماع «۵۱٪» برای فروشندگان کالای گران |
| باب (Bob)، صاحب کافه | خدمات پیمانکاری برونمرزی | برای ساخت وبسایت با گوپش (Gopesh)، توسعهدهندهٔ هندی در بنگالور قرارداد میبندد که با بیتکوین پول بگیرد؛ برونسپاری و حوالههای بینالمللی |
| گابریل (Gabriel)، نوجوان ریودوژانیرو | فروشگاه اینترنتی | تیشرت، لیوان و استیکر با طرح بیتکوین میفروشد؛ زیر سن داشتن حساب بانکی، ولی با تشویق والدین کسبوکار میکند |
| اوجنیا (Eugenia)، مدیر خیریهٔ کودکان در فیلیپین | کمکهای خیریه | از بیتکوین برای جذب اهداکنندگان داخلی و خارجی و پخش سریع وجوه به مناطق نیازمند استفاده میکند؛ دفتر کل باز برای شفافیت خیریهها |
| محمد (Mohammed)، واردکنندهٔ لوازم الکترونیکی در دبی | واردات/صادرات | برای خرید از آمریکا و چین و تسریع پرداختها بیتکوین به کار میبرد؛ پرداختهای بزرگ بینالمللی B2B مرتبط با کالای فیزیکی |
| جینگ (Jing)، دانشجوی مهندسی کامپیوتر در شانگهای | استخراج | دستگاه ماینینگ ساخته تا درآمد کسب کند؛ زیرساخت «صنعتی» بیتکوین، یعنی سختافزار تخصصی که شبکه را ایمن و ارز جدید منتشر میکند |
نویسنده تأکید میکند هر داستان بر پایهٔ افراد و صنایع واقعیای است که اکنون با بیتکوین بازارها و راهحلهای نو برای مسائل اقتصادی جهانی میسازند.
شروع کار
- بیتکوین پروتکلی است که با یک کلاینت (برنامهای که این پروتکل را «میفهمد») قابل دسترسی است. کیف پول بیتکوین رایجترین رابط کاربری آن است، همانطور که مرورگر وب رایجترین رابط پروتکل HTTP است. مانند مرورگرها، کیف پولها از نظر کیفیت، کارایی، امنیت، حریم خصوصی و اطمینانپذیری فرق دارند.
- پیادهسازی مرجع پروتکل شامل کیف پول است و «Satoshi Client» یا Bitcoin Core نام دارد که از پیادهسازی اصلی ناکاموتو مشتق شده است.
انتخاب کیف پول
کیف پولها از فعالترین بخشهای اکوسیستماند: رقابت شدید است و کیف پولهای سال قبل ممکن است دیگر نگهداری نشوند. انتخاب سلیقهای و وابسته به کاربرد و تخصص کاربر است؛ پس نویسنده برند خاصی توصیه نمیکند. چون انتقال پول میان کیف پولها ساده، ارزان و سریع است، آزمودن چند کیف پول معقول است.
دستهبندی بر اساس پلتفرم:
- کیف پول دسکتاپ (desktop wallet): نخستین نوع (پیادهسازی مرجع)؛ امکانات، استقلال و کنترل زیاد، اما اجرا روی سیستمعاملهای عمومی (ویندوز، macOS) که اغلب ناامن یا بد پیکربندی هستند، ضعف امنیتی دارد.
- کیف پول موبایل (mobile wallet): رایجترین نوع (iOS و Android)؛ بسیاری ساده و برای تازهکارها عالیاند، و نمونههای پرامکانات برای کاربران حرفهای هم هست.
- کیف پول وب (web wallet): از طریق مرورگر و روی سرور شخص ثالث ذخیره میشود (شبیه ایمیل تحت وب). برخی با کدی که در مرورگر کاربر اجرا میشود کلیدها را دست کاربر میگذارند، ولی بیشترشان برای سهولت، کنترل کلیدها را از کاربر میگیرند. نگهداری مبلغ زیاد روی سیستمهای شخص ثالث توصیه نمیشود.
- کیف پول سختافزاری (hardware wallet): دستگاهی با سختافزار اختصاصی که کیف پول مستقل و امن را اجرا میکند، از راه USB یا NFC کار میکند و چون همهٔ عملیات روی سختافزار تخصصی انجام میشود، برای مبالغ زیاد بسیار امن شمرده میشود.
- کیف پول کاغذی (paper wallet): چاپ کلیدها برای نگهداری بلندمدت (میتواند روی چوب، فلز و غیره هم باشد)؛ روش کمفناوری ولی بسیار امن. ذخیرهٔ آفلاین را «ذخیرهسازی سرد (cold storage)» هم مینامند.
دستهبندی بر اساس میزان استقلال و تعامل با شبکه:
- کلاینت گره کامل (full node): کل تاریخچهٔ تراکنشهای بیتکوین را نگه میدارد، کیف پول را مدیریت میکند و مستقیماً میتواند تراکنش بسازد. همهٔ جنبههای پروتکل را پیاده میکند و میتواند کل بلاکچین و هر تراکنش را مستقل اعتبارسنجی کند. منابع زیادی مصرف میکند (در زمان نگارش، بیش از ۱۲۵ گیگابایت دیسک و ۲ گیگابایت RAM) اما استقلال کامل و راستیآزمایی مستقل میدهد.
- کلاینت سبک (lightweight / SPV): برای دریافت اطلاعات تراکنش به گرههای کامل وصل میشود اما کیف پول را محلی نگه میدارد و خودش تراکنش میسازد، اعتبارسنجی و پخش میکند؛ بدون واسطه با شبکه تعامل دارد.
- کلاینت API شخص ثالث: از طریق APIهای سرویسدهندهٔ ثالث (نه اتصال مستقیم به شبکه) کار میکند؛ کیف پول ممکن است دست کاربر یا سرور ثالث باشد، اما همهٔ تراکنشها از شخص ثالث عبور میکنند.
سه ترکیب رایج: دسکتاپ با کلاینت کامل، موبایل سبک و وب با شخص ثالث؛ مرزها تار است چون بسیاری از کیف پولها چندپلتفرمیاند و به شیوههای مختلف به شبکه وصل میشوند. کتاب از انواع کلاینتهای قابل دانلود (از Bitcoin Core تا کیف پولهای موبایل و وب) استفاده میکند؛ بعضی مثالها به Bitcoin Core نیاز دارند چون علاوه بر کلاینت کامل، APIهایی برای کیف پول، شبکه و تراکنش در اختیار میگذارد، و هر که بخواهد با رابطهای برنامهنویسی کار کند باید Bitcoin Core یا کلاینت جایگزین را اجرا کند.
شروع سریع (Quick Start)
- آلیس کاربر فنی نیست و از طریق دوستش جو (Joe) با بیتکوین آشنا شده است. جو در یک مهمانی با شور بیتکوین را توضیح میدهد و نمایش میدهد. او کیف پول موبایل را برای تازهکارها بهترین میداند و آلیس برنامهٔ Mycelium را روی اندرویدش نصب میکند.
- Mycelium مانند بسیاری از کیف پولها در اولین اجرا خودکار یک کیف پول جدید میسازد. مهمترین بخش صفحه، آدرس بیتکوین آلیس است: رشتهای بلند از حروف و ارقام (در مثال کتاب
1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK) بههمراه یک کد QR که همان اطلاعات را به صورت بارکد قابل اسکن با دوربین گوشی نشان میدهد. با ضربه روی QR یا دکمهٔ Receive میتوان آن را کپی یا بزرگنمایی کرد. - نکتهها دربارهٔ آدرس:
- آدرسها با ۱ یا ۳ شروع میشوند.
- مانند آدرس ایمیل میتوان آن را با دیگران به اشتراک گذاشت تا مستقیم به کیف پول شما بیتکوین بفرستند؛ از نظر امنیتی چیز حساسی نیست و در هر جا میتوان آن را منتشر کرد.
- برخلاف ایمیل، هر قدر بخواهید آدرس جدید میسازید که همه به کیف پول شما میریزند؛ بسیاری از کیف پولهای امروزی برای حفظ حریم خصوصی برای هر تراکنش آدرس جدید میسازند. کیف پول در اصل مجموعهای از آدرسها و کلیدهایی است که وجوه را آزاد میکنند.
- کیف پول آلیس یک کلید خصوصی تصادفی و آدرس متناظرش را ساخته است. در این لحظه آدرس هنوز در هیچجای شبکه «ثبت» نشده؛ فقط عددی است متناظر با کلیدی که دسترسی به وجوه را کنترل میکند. این آدرس مستقل و بدون ارجاع به هیچ سرویسی ساخته میشود و در اغلب کیف پولها هیچ ارتباطی میان آدرس و اطلاعات هویتی نیست. تا لحظهای که آدرس بهعنوان گیرندهٔ ارزش در یک تراکنش روی دفتر کل بیاید، فقط یکی از آدرسهای بیشمار ممکن است و پس از آن جزء آدرسهای شناختهشدهٔ شبکه میشود.
گرفتن نخستین بیتکوین
دشوارترین کار کاربر تازه، به دست آوردن بیتکوین است؛ برخلاف ارزهای خارجی، هنوز نمیتوان آن را از بانک یا باجهٔ ارز خرید. ریشهٔ ماجرا بازگشتناپذیری تراکنشهای بیتکوین است، در حالی که کارت اعتباری، کارت بانکی، PayPal و حوالههای بانکی برگشتپذیرند. پس فروشندهٔ بیتکوین ریسک بالایی دارد که خریدار پس از دریافت بیتکوین پرداخت الکترونیکی را برگرداند. شرکتهایی که پرداخت الکترونیکی سنتی را میپذیرند معمولاً احراز هویت و اعتبارسنجی میخواهند که چند روز تا چند هفته طول میکشد؛ بنابراین کاربر تازه نمیتواند فوراً با کارت اعتباری بیتکوین بخرد.
روشهای تهیه:
- خرید مستقیم از دوستی که بیتکوین دارد (سادهترین؛ برای آشنایی میتوان به meetupهای محلی رفت).
- سرویسهای آگهی مانند localbitcoins.com برای خرید حضوری با پول نقد از فروشندهٔ نزدیک.
- فروش کالا یا خدمت در ازای بیتکوین (برنامهنویس: مهارت برنامهنویسی؛ آرایشگر: اصلاح مو).
- خودپرداز بیتکوین (Bitcoin ATM): دستگاهی که پول نقد میگیرد و بیتکوین به کیف پول موبایل میفرستد (نقشهٔ Coin ATM Radar).
- صرافی ارز دیجیتال متصل به حساب بانکی (فهرست صرافیهای هر ارز در سایتهایی مانند BitcoinAverage).
نکتهٔ حریم خصوصی: بیتکوین در صورت استفادهٔ درست حریم خصوصی بیشتری دارد و خرید، نگهداری و خرجکردن آن نیاز به افشای اطلاعات هویتی ندارد. اما در نقاطی که بیتکوین به سامانههای سنتی مثل صرافیها میرسد، مقررات ملی و بینالمللی معمولاً احراز هویت و اطلاعات بانکی میخواهد. وقتی آدرس به هویتی گره بخورد، همهٔ تراکنشهای مرتبط بهراحتی قابل شناسایی و ردیابی میشود؛ به همین دلیل بعضی کاربران حساب صرافی جداگانهای جدا از کیف پول خود نگه میدارند.
یافتن قیمت جاری بیتکوین
- پیش از خرید، آلیس و جو باید نرخ تبدیل بیتکوین به دلار را توافق کنند. پرسش رایج تازهکارها: «چه کسی قیمت را تعیین میکند؟» پاسخ کوتاه: بازار.
- بیتکوین نرخ ارز شناور (floating) دارد و ارزشش در برابر هر ارز دیگر با عرضه و تقاضا در بازارهای مختلف تغییر میکند. «قیمت» دلاری در هر بازار از آخرین معامله محاسبه میشود و ممکن است چند بار در ثانیه جزئی تغییر کند. سرویسهای قیمتگذاری قیمت چند بازار را جمع و میانگین وزنی بر اساس حجم (volume-weighted) میگیرند (جفتارز مثل BTC/USD).
- نمونه ابزارها: BitcoinAverage (میانگین وزنی ساده برای هر ارز)، CoinCap (ارزش بازار و نرخ صدها ارز رمزنگاریشده)، نرخ مرجع بیتکوین CME (برای مراجع نهادی و قراردادی، بخشی از دادههای سرمایهگذاری CME). اکثر کیف پولها هم خودکار مبالغ را به ارز محلی تبدیل میکنند.
ارسال و دریافت بیتکوین
داستان گامبهگام آلیس و جو:
- آلیس تصمیم میگیرد ۱۰ دلار را به بیتکوین تبدیل کند تا ریسک زیادی نکند؛ ۱۰ دلار نقد به جو میدهد و در Mycelium گزینهٔ Receive را میزند تا QR با اولین آدرسش نشان داده شود.
- جو در کیف پول گوشیاش Send را میزند و دو ورودی میبیند: آدرس مقصد و مبلغ (بر حسب BTC یا ارز محلی). با آیکون QR کنار فیلد آدرس، دوربین را روشن میکند و کد روی گوشی آلیس را اسکن میکند تا مجبور نباشد آدرس طولانی را تایپ کند.
- جو ۱۰ دلار را وارد میکند و کیف پول آخرین نرخ را از سرویس آنلاین میگیرد؛ نرخ آن روز ۱۰۰ دلار برای هر بیتکوین است، پس ۱۰ دلار = ۰٫۱۰ BTC یا ۱۰۰ میلیبیتکوین (mBTC).
- جو با دقت آدرس و مبلغ را بازبینی میکند چون اشتباه برگشتناپذیر است و Send را میزند. کیف پول یک تراکنش میسازد که ۰٫۱۰ BTC را به آدرس آلیس اختصاص میدهد، از وجوه کیف پول جو تأمین میکند و آن را با کلیدهای خصوصی جو امضا میکند. این امضا به شبکه میگوید جو انتقال ارزش به آدرس جدید را مجاز کرده است.
- تراکنش از طریق پروتکل همتابههمتا به سرعت در شبکه پخش میشود؛ کمتر از یک ثانیه، بیشتر گرههای خوبمتصل آن را دریافت و آدرس آلیس را برای نخستین بار میبینند.
- کیف پول آلیس مدام به تراکنشهای منتشرشده «گوش میدهد» و به دنبال آدرسهای خودش است؛ چند ثانیه پس از پخش، دریافت ۰٫۱۰ BTC را نشان میدهد.
کادر: تأییدها (Confirmations)
در ابتدا تراکنش جو در آدرس آلیس «تأییدنشده (Unconfirmed)» نشان داده میشود؛ یعنی در شبکه پخش شده اما هنوز در دفتر کل (بلاکچین) ثبت نشده. برای تأیید باید در یک بلاک قرار گیرد و به بلاکچین اضافه شود که بهطور میانگین هر ۱۰ دقیقه رخ میدهد؛ این، در اصطلاح مالی سنتی، «تسویه (clearing)» است. جزئیات پخش، اعتبارسنجی و تأیید در فصل ۱۰ آمده است.
آلیس اکنون مالک ۰٫۱۰ BTC قابل خرج است؛ فصل بعد نخستین خرید او و فناوریهای زیرین را بررسی میکند.
جمعبندی
- بیتکوین مجموعهای از چهار جزء است: شبکهٔ همتابههمتا، بلاکچین، قواعد اجماع و اثبات کار؛ ارزی کاملاً مجازی که مالکیت آن با تسلط بر کلید خصوصی تعریف میشود و در تراکنشها مستتر است.
- عرضهٔ آن سقف حدود ۲۱ میلیون دارد، هر چهار سال نرخ انتشارش نصف میشود، و سختی استخراج برای حفظ بلاکهای ۱۰ دقیقهای خودکار تنظیم میشود.
- ریشهٔ فکری: ارزهای دیجیتال متمرکز پیشین شکست خوردند، و ناکاموتو در ۲۰۰۸ با ترکیب ایدههایی چون HashCash و b-money و راهحل ژنرالهای بیزانسی از طریق اثبات کار، دوبارخرج را بدون مرجع مرکزی حل کرد.
- کتاب با داستان آدمها (آلیس، باب، کارول، گوپش، گابریل، اوجنیا، محمد، جینگ) پیش میرود و کیف پولها را بر اساس پلتفرم (دسکتاپ، موبایل، وب، سختافزاری، کاغذی) و میزان استقلال (گره کامل، سبک/SPV، API ثالث) دستهبندی میکند.
- در «شروع سریع»، آلیس با Mycelium آدرس میسازد (بدون ثبت در شبکه)، از جو ۰٫۱۰ BTC معادل ۱۰ دلار با نرخ ۱۰۰ دلار میخرد؛ تراکنش با امضای جو ساخته و پخش میشود و تا ثبت در بلاک «تأییدنشده» میماند. تراکنشها بازگشتناپذیر و قیمت بازار شناور است و حریم خصوصی تا اتصال آدرس به هویت (مثلاً در صرافی) حفظ میشود.
فصل ۲ — بیتکوین چگونه کار میکند (How Bitcoin Works)
فصل با عنوان فرعی «تراکنشها، بلاکها، استخراج و بلاکچین» یک نمای کلان از بیتکوین میدهد: سامانهای که بر اعتماد غیرمتمرکز بنا شده و برخلاف بانکها و سامانههای پرداخت سنتی، به جای یک مرجع مورد اعتماد، اعتماد را بهعنوان خاصیتی برآمده از تعامل شرکتکنندگان میسازد. روش فصل این است که یک تراکنش واحد را دنبال کنیم: از لحظهٔ ساختهشدن، عبور از شبکه، «مورد اعتماد» شدن از راه اجماع توزیعشده و سرانجام ثبت در بلاکچین. جزئیات فناوری در فصلهای بعد میآید.
نمای کلی بیتکوین
- سامانه از این اجزا تشکیل شده است: کاربران با کیف پولهایی که کلید دارند، تراکنشهایی که در شبکه پخش میشوند و ماینرها که با محاسبات رقابتی بلاکچین اجماعی (دفتر کل مرجع همهٔ تراکنشها) را تولید میکنند.
- مثالهای فصل بر پایهٔ تراکنشهای واقعی روی شبکهٔ بیتکوین است که تعامل جو، آلیس، باب و گوپش را با انتقال وجه بین کیف پولها شبیهسازی میکنند.
- ابزار دنبالکردن: مرورگر بلاکچین (blockchain explorer)، برنامهٔ وبی که مانند موتور جستوجوی بیتکوین عمل میکند و امکان جستوجوی آدرس، تراکنش و بلاک و دیدن روابط و جریان بین آنها را میدهد. نمونهها: Bitcoin Block Explorer، BlockCypher Explorer، blockchain.info و BitPay Insight. همه میتوانند با آدرس، هش تراکنش، شمارهٔ بلاک یا هش بلاک جستوجو کنند.
خرید یک فنجان قهوه
- آلیس تازه ۰٫۱۰ BTC گرفته و حالا میخواهد در کافهٔ باب (پالو آلتو، کالیفرنیا) قهوه بخرد. قیمتهای کافه به دلار است اما صندوق (POS) باب هر دو ارز را میپذیرد و به نرخ بازار تبدیل میکند: ۱٫۵۰ دلار = ۰٫۰۱۵ BTC (باب میگوید «پانزده میلیبیت»).
- سامانهٔ باب یک کد QR درخواست پرداخت هم میسازد. برخلاف QR که فقط آدرس دارد، این یک URL است که آدرس مقصد، مبلغ و توضیح را حمل میکند تا کیف پول فیلدها را پیشپر کند و توضیح خوانا نشان دهد. قالب:
bitcoin:<address>?amount=0.015&label=Bob%27s%20Cafe&message=Purchase%20at%20Bob%27s%20Cafeکه اجزایش عبارتند از:- آدرس بیتکوین (در مثال کتاب
1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA) - مبلغ پرداخت:
0.015 - برچسب برای آدرس گیرنده: «Bob’s Cafe»
- توضیح پرداخت: «Purchase at Bob’s Cafe»
- آدرس بیتکوین (در مثال کتاب
- آلیس QR را اسکن میکند، گوشی پرداخت ۰٫۰۱۵۰ BTC به کافهٔ باب را نشان میدهد و با زدن Send مجوز میدهد. طی چند ثانیه (تقریباً مثل تأیید کارت اعتباری) باب تراکنش را روی صندوق میبیند.
- نکتهٔ واحد: شبکه میتواند مقادیر کسری را جابهجا کند؛ از میلیبیتکوین (یکهزارم) تا یک صدمیلیونیوم بیتکوین که ساتوشی (satoshi) نام دارد. کتاب واژهٔ «بیتکوین» را برای هر مقداری، از ۱ ساتوشی تا کل ۲۱٬۰۰۰٬۰۰۰ بیتکوینی که استخراج خواهد شد، به کار میبرد.
- تراکنش آلیس به کافهٔ باب را میتوان در مرورگر بلاک (مثال ۲-۱) با شناسهاش
0627052b6f28912f…c345c2f2دید.
تراکنشهای بیتکوین
به زبان ساده، تراکنش به شبکه میگوید مالک مقداری ارزش، انتقال آن را به مالک دیگر مجاز کرده است. مالک جدید میتواند با تراکنش بعدی آن را به مالک بعدی منتقل کند و همینطور زنجیرهٔ مالکیت شکل میگیرد.
ورودیها و خروجیهای تراکنش
- تراکنش مانند یک سطر در دفتر حسابداری دوطرفه (double-entry) است. هر تراکنش یک یا چند ورودی (input) دارد که مانند بدهکار کردن یک حساباند، و یک یا چند خروجی (output) که مانند بستانکار کردن حساب.
- ورودیها و خروجیها لزوماً برابر نیستند: مجموع خروجیها کمی کمتر از ورودیهاست و تفاوت، کارمزد ضمنی تراکنش است؛ پرداخت کوچکی که ماینرِ گنجانندهی تراکنش در دفتر کل جمع میکند.
- تراکنش برای هر مقدار بیتکوین ورودی که خرج میشود اثبات مالکیت هم دارد: امضای دیجیتال مالک که هر کسی مستقل میتواند آن را راستیآزمایی کند. «خرج کردن» در اصطلاح بیتکوین یعنی امضای تراکنشی که ارزش را از تراکنش قبلی به مالک جدیدِ مشخصشده با یک آدرس منتقل میکند.
زنجیرهٔ تراکنشها
- پرداخت آلیس به باب، خروجی یک تراکنش پیشین را بهعنوان ورودی به کار میبرد: تراکنش جو که در ازای پول نقد ارزشی قفلشده با کلید آلیس ساخت. تراکنش جدید به آن ارجاع میدهد و خروجیهای تازه برای پرداخت قهوه و دریافت باقیمانده میسازد.
- به این ترتیب ورودیهای جدیدترین تراکنش با خروجیهای تراکنشهای قبلی متناظرند. کلید آلیس امضایی میدهد که آن خروجیهای قبلی را باز (unlock) میکند و مالکیت وجوه را به شبکه ثابت میکند. پرداخت قهوه به آدرس باب «گرهخورده (encumbered)» میشود: برای خرجکردنش باب باید امضا بدهد. زنجیره: جو ← آلیس ← باب (و بعدها گوپش).
دادن باقیمانده (Change)
- بسیاری از تراکنشها خروجیای دارند که هم به آدرس مالک جدید و هم به آدرس مالک فعلی (آدرس باقیمانده / change address) ارجاع میدهد؛ چون ورودیهای تراکنش مثل اسکناس تقسیمناپذیرند. اگر کالای ۵ دلاری را با اسکناس ۲۰ دلاری بخرید، ۱۵ دلار برمیگردد؛ در بیتکوین هم اگر کالای ۵ بیتکوینی را با ورودی ۲۰ بیتکوینی بخرید، یک خروجی ۵ تایی برای فروشنده و یک خروجی ۱۵ تایی (منهای کارمزد) به خودتان میفرستید.
- آدرس باقیمانده لازم نیست با آدرس ورودی یکی باشد و به دلایل حریم خصوصی اغلب آدرس جدیدی از همان کیف پول است.
- راهبرد کیف پولها در جمعکردن ورودیها متفاوت است: ترکیب چند ورودی کوچک یا استفاده از یک ورودی برابر یا بزرگتر از مبلغ. مگر اینکه دقیقاً مبلغ بهعلاوهٔ کارمزد جور شود، باقیمانده لازم است. تشبیه نقدی: اگر همیشه بزرگترین اسکناس را خرج کنید جیبتان پر از خرد میشود، اگر فقط خرد را خرج کنید همیشه فقط اسکناس درشت میماند؛ آدمها ناخودآگاه تعادلی بین این دو مییابند و سازندگان کیف پول میکوشند همین تعادل را برنامهنویسی کنند.
- خلاصه: تراکنش ارزش را از ورودیها به خروجیها میبرد؛ ورودی ارجاع به خروجی تراکنش قبلی است (منشأ ارزش)، خروجی ارزش مشخصی را به آدرس مالک جدید میدهد و میتواند یک خروجی باقیمانده به مالک اولیه داشته باشد.
شکلهای رایج تراکنش
| شکل | توضیح |
|---|---|
| یک ورودی، دو خروجی | رایجترین: پرداخت ساده از یک آدرس به آدرس دیگر همراه با باقیمانده |
| چند ورودی، یک خروجی (تجمیع) | مثل تعویض انبوهی از سکه و اسکناس خرد با یک اسکناس بزرگ؛ کیف پولها برای پاکسازی مبالغ کوچک دریافتی (باقیماندهها) میسازند |
| یک ورودی، چند خروجی (توزیع) | پرداخت به چند گیرنده؛ مثلاً شرکتهایی که حقوق چند کارمند را یکجا میپردازند |
ساخت یک تراکنش
- کیف پول آلیس همهٔ منطق انتخاب ورودیها و خروجیهای مناسب را دارد؛ آلیس فقط مقصد و مبلغ را مشخص میکند و بقیه بدون دیدن جزئیات انجام میشود.
- کیف پول حتی آفلاین هم میتواند تراکنش بسازد و امضا کند؛ مثل نوشتن چک در خانه و فرستادن بعدی آن در پاکت به بانک. لازم نیست هنگام ساخت به شبکه وصل باشد.
انتخاب ورودیهای درست
- کیف پول باید ورودیهایی بیابد که مبلغ را پوشش دهند. بیشتر کیف پولها فهرست خروجیهای خرجنشده (UTXO) متعلق به آدرسهای خود را نگه میدارند؛ پس کیف پول آلیس نسخهای از خروجی تراکنش جو را دارد.
- کیف پول گره کامل نسخهٔ همهٔ UTXOهای بلاکچین را دارد و میتواند هم ورودی بسازد و هم ورودی تراکنشهای دریافتی را سریع راستیآزمایی کند. اما چون فضای دیسک زیادی میخواهد، بیشتر کیف پولهای کاربران «سبک» هستند و فقط UTXOهای خود کاربر را دنبال میکنند.
- اگر کیف پول خروجیهای خرجنشده را نگه نمیدارد، میتواند با APIهای ارائهدهندگان مختلف یا پرسوجو از یک گره کامل آنها را بگیرد. مثال ۲-۲ یک درخواست HTTP GET با
curlبه blockchain.info (/unspent?active=<address>) نشان میدهد که خروجی JSON آن یکunspent_outputsاست با فیلدهایی مثلtx_hash،tx_output_n(اندیس خروجی در تراکنش)،script(اسکریپت قفل)،valueوconfirmations. مقدار در مثال ۱۰٬۰۰۰٬۰۰۰ ساتوشی است، یعنی ۰٫۱۰ BTC. - اگر یک UTXO برای قهوه کافی نبود، کیف پول مجبور بود مثل برداشتن سکه از کیف پول خرد، چند خروجی کوچکتر را پیدا کند تا به مبلغ برسد. در هر دو حالت ممکن است باقیمانده لازم شود.
ساخت خروجیها
- هر خروجی به شکل یک اسکریپت ساخته میشود که روی ارزش «بار تعهد (encumbrance)» میگذارد و فقط با ارائهٔ راهحل آن اسکریپت قابل خرج است. به زبان ساده خروجی آلیس میگوید: «این خروجی قابل پرداخت به هر که امضایی از کلید متناظر آدرس عمومی باب ارائه کند». چون فقط کیف پول باب کلید آن آدرس را دارد، فقط او میتواند آن را خرج کند. (این همان اسکریپت قفل / locking script است.)
- تراکنش یک خروجی دوم هم لازم دارد چون وجه آلیس ۰٫۱۰ BTC است و قهوه ۰٫۰۱۵ BTC؛ پس ۰٫۰۸۵ BTC باید برگردد. این باقیمانده خروجی در همان تراکنش است که به خود آلیس پرداخت میشود و بعداً میتواند خرجش کند.
- کارمزد بهصورت صریح در تراکنش نیست و از تفاوت ورودیها و خروجیها استنباط میشود. مثلاً اگر آلیس به جای ۰٫۰۸۵ فقط ۰٫۰۸۴۵ به خودش برگرداند، ۰٫۰۰۰۵ BTC (نیم میلیبیت) باقی میماند که ماینر برای اعتبارسنجی و گنجاندن تراکنش در بلاک جمع میکند.
- تراکنش حاصل در مرورگر بلاک قابل مشاهده است.
افزودن تراکنش به دفتر کل
- تراکنشی که کیف پول آلیس ساخت ۲۵۸ بایت است و هر آنچه برای اثبات مالکیت و تعیین مالکان جدید لازم است در خود دارد. حال باید به شبکه ارسال شود تا جزئی از بلاکچین شود.
ارسال تراکنش
- چون تراکنش همهٔ اطلاعات لازم برای پردازش را دارد، مهم نیست از کجا یا چگونه به شبکه ارسال شود. شبکهٔ بیتکوین همتابههمتاست و هر کلاینت به چند کلاینت دیگر وصل است؛ هدف شبکه پخش تراکنشها و بلاکها به همهٔ شرکتکنندگان است.
چگونه پخش میشود
- هر سامانه (سرور، برنامهٔ دسکتاپ یا کیف پول) که با زبان پروتکل بیتکوین در شبکه شرکت کند یک گره بیتکوین (node) نامیده میشود. کیف پول آلیس میتواند تراکنش را از راه هر نوع اتصال (سیمی، Wi-Fi، موبایل) به هر گرهٔ متصل بفرستد. لازم نیست مستقیماً به کیف پول باب وصل شود یا از اینترنت کافه استفاده کند، هرچند ممکن است.
- هر گرهای که تراکنش معتبر جدیدی دریافت کند، فوراً آن را به همهٔ گرههای متصل میفرستد؛ تکنیک پخش به نام flooding. تراکنش در عرض چند ثانیه به درصد بالایی از گرهها میرسد.
دید باب
- کیف پول باب (حتی اگر مستقیم وصل نباشد) ظرف چند ثانیه تراکنش را میگیرد و چون خروجیاش با کلیدهای باب قابل خرج است، آن را پرداخت ورودی تشخیص میدهد. باب میتواند مستقل بررسی کند که تراکنش خوشساخت است، از ورودیهای خرجنشده استفاده میکند و کارمزد کافی برای ورود به بلاک بعدی دارد. در این لحظه باب با ریسک کمی فرض میکند بهزودی در بلاک تأیید میشود.
- باور غلط رایج: لازم نیست برای هر پرداخت ۱۰ دقیقه برای بلاک یا تا ۶۰ دقیقه برای شش تأیید صبر کرد. تأییدها اطمینان میدهند که کل شبکه تراکنش را پذیرفته، اما برای اقلام کمارزش مثل قهوه این تأخیر لازم نیست؛ پذیرش پرداخت معتبر بدون تأیید ریسکی بیش از پذیرش کارت اعتباری بدون ارائهٔ شناسه یا امضا ندارد، که فروشندگان همواره میپذیرند.
استخراج بیتکوین
- تراکنش آلیس در شبکه پخش شده اما تا زمانی که توسط فرایند استخراج (mining) راستیآزمایی و در یک بلاک گنجانده نشود، جزء بلاکچین نیست (جزئیات در فصل ۱۰).
- سامانهٔ اعتماد بیتکوین بر محاسبه بنا شده است: تراکنشها در بلاکها دسته میشوند و اثبات بلاک محاسبات عظیمی میخواهد اما راستیآزمایی اثباتشده بودن آن تنها اندکی محاسبه میطلبد. استخراج دو هدف دارد:
- اعتبارسنجی تراکنشها: گرههای استخراجکننده همه تراکنشها را بر اساس قواعد اجماع بیتکوین میسنجند و تراکنشهای نامعتبر یا بدساخت را رد میکنند؛ پس امنیت تراکنشها را فراهم میکنند.
- ایجاد بیتکوین جدید در هر بلاک (تقریباً مثل چاپ پول بانک مرکزی) با مقدار محدود و نزولی بر اساس برنامهٔ ثابت انتشار.
- استخراج تعادلی ظریف بین هزینه و پاداش برقرار میکند: استخراج برق مصرف میکند تا مسئلهای ریاضی حل شود و ماینر موفق پاداش (بیتکوین جدید و کارمزدها) میگیرد، اما فقط اگر همهٔ تراکنشها را مطابق قواعد اجماع درست راستیآزمایی کرده باشد. این تعادل امنیت را بدون مرجع مرکزی میدهد.
- تشبیه سودوکو: استخراج مانند یک سودوکوی غولپیکر رقابتی است که هر بار کسی آن را حل کند ریست میشود و سختیاش خودکار طوری تنظیم میشود که حل آن حدود ۱۰ دقیقه طول بکشد. جدول کاملشده را بهسرعت میتوان راستیآزمایی کرد، اما حل جدولی که اندکی پر شده کار زیادی میطلبد. با تغییر اندازهٔ جدول سختی تنظیم میشود ولی راستیآزمایی هم برای جدول بزرگ ساده است. «معمای» بیتکوین بر پایهٔ هش رمزنگاری است و همین خاصیت را دارد: حل آن دشوار و تأییدش آسان است (عدم تقارن) و سختیاش قابل تنظیم.
داستان جینگ
- جینگ (شانگهای) مزرعهٔ استخراج دارد: کسبوکاری با هزاران رایانهٔ استخراج تخصصی. هر ۱۰ دقیقه ماشینهای او با هزاران سامانهٔ مشابه در مسابقهٔ جهانی برای حل یک بلاک تراکنش رقابت میکنند. یافتن راهحل، یعنی اثبات کار (PoW)، در سطح شبکه به چند کوادریلیون هش در ثانیه نیاز دارد. الگوریتم: تکرار هشکردن سرآیند بلاک (block header) بههمراه یک عدد تصادفی با SHA256 تا الگویی از پیش تعیینشده پدید آید. نخستین ماینری که جواب را بیابد برندهٔ دور است و بلاک را منتشر میکند.
- جینگ در ۲۰۱۰ با یک رایانهٔ رومیزی بسیار سریع شروع کرد. با ورود ماینرهای بیشتر، سختی مسئله بهسرعت بالا رفت و ماینرها به GPUهای پیشرفته (مثل کارتهای گرافیک بازی) ارتقا دادند؛ و در زمان نگارش کتاب، سختی آنقدر زیاد است که فقط با ASIC (مدار مجتمع کاربرد-خاص، یعنی صدها الگوریتم استخراج چاپشده در سختافزار که موازی روی یک تراشه اجرا میشود) سودآور است.
- شرکت جینگ در یک استخر استخراج (mining pool) هم شرکت میکند؛ مثل صندوق قرعهکشی گروهی که چند نفر تلاش و پاداش را تقسیم میکنند. اکنون انبار او هزاران ASIC دارد که ۲۴ ساعته کار میکنند و هزینهٔ برق را از فروش بیتکوین استخراجشده میپردازد؛ سود، درآمد او را میسازد.
استخراج تراکنشها در بلاکها
- تراکنشهای جدید دائم از کیف پولها و برنامهها میرسند. گرهها آنها را به استخر موقت تراکنشهای تأییدنشده (مخزن تراکنشهای تأییدنشده / mempool) هر گره اضافه میکنند. ماینر هنگام ساخت بلاک جدید از این استخر تراکنش برمیدارد و میکوشد درستی بلاک را با الگوریتم اثبات کار اثبات کند.
- تراکنشها به ترتیب بیشترین کارمزد (و چند معیار دیگر) اولویت میگیرند. هر ماینر به محض دریافت بلاک قبلی از شبکه (و اینکه دور قبل را باخته) کار بلاک جدید را آغاز میکند: فوراً بلاک تازهای میسازد، آن را با تراکنشها و اثرانگشت (هش) بلاک قبلی پر میکند و محاسبهٔ اثبات کار را آغاز میکند.
- هر ماینر یک تراکنش ویژه در بلاکش میگذارد که پاداش بلاک (در زمان نگارش، ۱۲٫۵ بیتکوین تازهساخته) بهعلاوهٔ مجموع کارمزدهای همهٔ تراکنشهای بلاک را به آدرس خودش میپردازد (تراکنش coinbase). اگر جوابی بیابد که بلاک را معتبر کند، «برنده» میشود چون بلاکش به بلاکچین سراسری افزوده و تراکنش پاداشش قابل خرج میشود. جینگ که در استخر است نرمافزارش را طوری تنظیم میکند که پاداش به آدرس استخر برود؛ سپس سهمی از پاداش متناسب با کار انجامشده در دور آخر بین جینگ و دیگر ماینرها پخش میشود.
- تراکنش آلیس در استخر تأییدنشده بود، پس از اعتبارسنجی نرمافزار استخراج در بلاک نامزد (candidate block) استخر جینگ قرار گرفت و همهٔ ماینرهای آن استخر شروع به محاسبهٔ اثبات کار برای آن کردند. حدود پنج دقیقه پس از اولین پخش تراکنش، یکی از ASICهای جینگ جواب را یافت و به شبکه اعلام کرد. پس از آنکه سایر ماینرها بلاک برنده را تأیید کردند، مسابقهٔ بلاک بعدی را آغاز کردند.
- بلاک برنده جینگ شد بلاک شمارهٔ ۲۷۷۳۱۶ با ۴۲۰ تراکنش از جمله تراکنش آلیس. بلاکی که تراکنش در آن است یک تأیید (confirmation) حساب میشود.
- حدود ۱۹ دقیقه بعد ماینری دیگر بلاک ۲۷۷۳۱۷ را استخراج کرد؛ چون روی بلاک ۲۷۷۳۱۶ ساخته شده، محاسبهٔ بیشتری به بلاکچین افزود و اعتماد به آن تراکنشها را بیشتر کرد. هر بلاک جدید که روی بلاکِ حاوی تراکنش استخراج شود یک تأیید اضافه است. با انباشتهشدن بلاکها، برگرداندن تراکنش بهصورت نمایی دشوارتر و تراکنش مورد اعتمادتر میشود.
- در نمودار ۲-۹ بلاک ۲۷۷۳۱۶ دیده میشود که زیر آن ۲۷۷٬۳۱۶ بلاک دیگر (از جمله بلاک صفر) در زنجیره به هم پیوند خوردهاند تا برسد به بلاک ۰ که بلاک پیدایش (genesis block) نام دارد. با افزایش «ارتفاع» زنجیره، سختی محاسباتی هر بلاک و کل زنجیره بالا میرود. طبق قرارداد، هر بلاک با بیش از شش تأیید برگشتناپذیر فرض میشود، چون باطلکردن و بازمحاسبهٔ شش بلاک محاسبات عظیمی میطلبد.
خرج کردن تراکنش
- حالا که تراکنش آلیس در یک بلاک جای گرفته، بخشی از دفتر کل توزیعشده است و برای همهٔ برنامههای بیتکوین قابل مشاهده. هر کلاینت میتواند مستقل آن را معتبر و قابل خرج راستیآزمایی کند. کلاینتهای گره کامل میتوانند منبع وجوه را از لحظهای که بیتکوین در یک بلاک تولید شد، گامبهگام از تراکنشی به تراکنش دیگر تا آدرس باب دنبال کنند. کلاینتهای سبک میتوانند راستیآزمایی ساده پرداخت (SPV) انجام دهند: تأیید اینکه تراکنش در بلاکچین است و چند بلاک بعد از آن استخراج شده، که اطمینان میدهد ماینرها آن را معتبر پذیرفتهاند.
- باب اکنون میتواند خروجی این و تراکنشهای دیگر را خرج کند؛ مثلاً به پیمانکار یا تأمینکننده بپردازد. به احتمال زیاد نرمافزار باب پرداختهای کوچک را در پرداخت بزرگتری تجمیع میکند، مثلاً کل درآمد بیتکوینی روز در یک تراکنش با یک خروجی و یک آدرس (نمودار ۲-۶).
- با خرجکردن پرداختهای آلیس و مشتریان دیگر، باب زنجیرهٔ تراکنشها را بلندتر میکند. وقتی باب به طراح وبش گوپش در بنگالور برای صفحهٔ جدید پرداخت کند، زنجیره میشود جو ← آلیس ← باب ← گوپش (نمودار ۲-۱۰).
جمعبندی
- بیتکوین بر اعتماد غیرمتمرکز بنا شده است: کاربران با کلید و کیف پول، تراکنشها در شبکهٔ همتابههمتا با flooding پخش میشوند و ماینرها با اثبات کار بلاکچین اجماعی را میسازند.
- هر تراکنش ورودیهایی دارد (ارجاع به خروجیهای خرجنشده قبلی همراه با امضا) و خروجیهایی (اسکریپت قفل برای مالکان جدید و احتمالاً خروجی باقیمانده). تفاوت مجموع ورودی و خروجی کارمزد ضمنی است؛ ورودیها تقسیمناپذیرند و به همین دلیل «باقیمانده» لازم میشود. تراکنش آلیس: ورودی ۰٫۱۰ BTC، خروجی ۰٫۰۱۵ برای باب، باقیمانده برای خودش و کارمزد از تفاوت؛ حجم ۲۵۸ بایت.
- استخراج هم تراکنشها را اعتبارسنجی میکند و هم بیتکوین جدید میسازد (پاداش ۱۲٫۵ BTC در زمان نگارش بهعلاوهٔ کارمزدها)، با مسئلهٔ هشی که حلش سخت و تأییدش آسان است و سختیاش قابل تنظیم. تراکنش آلیس در بلاک ۲۷۷۳۱۶ (۴۲۰ تراکنش) توسط استخر جینگ حدود پنج دقیقه پس از پخش ثبت شد و هر بلاک بعدی تأیید میافزاید؛ بیش از شش تأیید بهطور قراردادی برگشتناپذیر است.
- برای مبالغ کم (قهوه) لازم نیست منتظر تأیید ماند؛ اما سطح تأیید لازم به ارزش تراکنش بستگی دارد.
- بعد از ثبت، باب (و هر کلاینت) میتواند خروجی را خرج کند و زنجیره را ادامه دهد. فصلهای بعدی فناوری کیف پول، آدرس، امضا، تراکنش، شبکه و استخراج را بهتفصیل بررسی میکنند.
فصل ۳ — بیتکوین کور: پیادهسازی مرجع (Bitcoin Core: The Reference Implementation)
مقدمه: پروژهای متنباز با یک پیادهسازی مرجع
- بیتکوین یک پروژهٔ متنباز است و کد منبع آن با مجوز MIT برای هر استفادهای آزاد است. «متنباز» فقط به معنای رایگانبودن نیست؛ یعنی توسعه توسط جامعهای باز از داوطلبان پیش میرود. در ابتدا این جامعه فقط ساتوشی ناکاموتو بود؛ تا سال ۲۰۱۶ بیش از ۴۰۰ مشارکتکننده داشت که حدود دهها نفر تماموقت یا پارهوقت روی کد کار میکردند. هر کسی (از جمله خواننده) میتواند مشارکت کند.
- نکتهٔ تاریخی: نرمافزار پیش از نگارش وایتپیپر کامل شده بود، چون ساتوشی میخواست قبل از توضیحدادن، از کارکرد آن مطمئن شود. نخستین پیادهسازی که با نام «Bitcoin» یا «کلاینت ساتوشی» شناخته میشد، بهتدریج اصلاح شد و به Bitcoin Core تبدیل شد تا از دیگر پیادهسازیهای سازگار متمایز شود.
- Bitcoin Core پیادهسازی مرجع (reference implementation) است، یعنی مرجع معتبر برای نحوهٔ پیادهسازی هر بخش از فناوری. شامل کیف پول، موتور اعتبارسنجی تراکنش و بلاک و یک گره (node) کامل شبکهٔ همتابههمتا است.
- هشدار: کیف پول داخلی Bitcoin Core برای استفادهٔ تولیدی کاربران یا برنامهها در نظر گرفته نشده است. توسعهدهندگان باید کیف پول را با استانداردهای مدرن مثل BIP-39 (عبارت یادآور) و BIP-32 (کیف پول HD) بسازند. BIP مخفف Bitcoin Improvement Proposal است.
- شکل ۳-۱ معماری Bitcoin Core را نشان میدهد (اجزای کیف پول، اعتبارسنجی، شبکه و …).
محیط توسعهٔ بیتکوین
فصل بهشدت فنی است و برای کسانی است که میخواهند محیط توسعه بسازند؛ کسی که این کار را نمیکند میتواند به فصل بعد برود. مثالها در پوستهٔ خط فرمان (shell) اجرا میشوند و نشانهٔ $ اعلان پوسته است و نباید تایپ شود.
کامپایل Bitcoin Core از کد منبع
- دریافت کد: با دانلود ZIP از GitHub یا با
git clone https://github.com/bitcoin/bitcoin.git(حدود ۶۶ هزار شیء، حدود ۶۳ مگابایت) و سپسcd bitcoin. git پرکاربردترین سامانهٔ کنترل نسخهٔ توزیعشده است. - انتخاب نسخهٔ انتشار: پیشفرض، جدیدترین کد است که ممکن است ناپایدار یا بتا باشد. با
git tagفهرست برچسبها دیده میشود. طبق قرارداد، نسخههای کاندیدا برای آزمایش پسوند rc دارند و نسخههای پایدار بدون پسوندند. کتاب در زمان نگارشv0.11.2را انتخاب میکند:git checkout v0.11.2و باgit statusوضعیت «HEAD detached at v0.11.2» تأیید میشود. - پیکربندی ساخت: مستندات در
README.mdوdoc/build-unix.md(برای مکbuild-osx.mdو برای ویندوزbuild-windows.md) آمدهاند. پیشنیازها (کتابخانههای لازم) باید قبل از ساخت نصب شوند؛ نبودنشان باعث خطا میشود و پس از نصب میتوان از همان نقطه ادامه داد.- از نسخهٔ 0.9 به بعد سامانهٔ ساخت autogen / configure / make است. ابتدا
./autogen.shاسکریپتهای پیکربندی خودکار میسازد، سپس./configureکتابخانهها را کشف و اسکریپت ساخت سفارشی تولید میکند../configure --helpگزینهها را نشان میدهد (الگوی--enable-FEATUREو--disable-FEATURE). - گزینههای مفید:
- از نسخهٔ 0.9 به بعد سامانهٔ ساخت autogen / configure / make است. ابتدا
| گزینه | کاربرد |
|---|---|
--prefix=$HOME |
تغییر مسیر نصب (پیشفرض /usr/local/)؛ مفید در آزمایشگاههای دانشگاهی |
--disable-wallet |
حذف کیف پول مرجع |
--with-incompatible-bdb |
اجازهٔ استفاده از نسخهٔ ناسازگار Berkeley DB برای کیف پول |
--with-gui=no |
ساختنکردن رابط گرافیکی (نیازمند Qt)؛ فقط سرور و خط فرمان |
- کامپایل: دستور
make(تا حدود یک ساعت، بسته به CPU و حافظه). در صورت قطع یا خطا با اجرای دوبارهٔmakeاز ادامه میتوان پیش رفت. خروجی شامل خطوطCXXبرای کامپایل ماژولهایی چونsha256،ripemd160،hmac_sha512،transaction،pubkeyوinterpreterاست. - نصب:
sudo make installفایلهای اجراییbitcoind،bitcoin-cliوbitcoin-txرا در/usr/local/binقرار میدهد و باwhich bitcoindوwhich bitcoin-cliنصب تأیید میشود.
اجرای یک گره Bitcoin Core
چرا و با چه منابعی
- شبکهٔ همتابههمتای بیتکوین از گرههای داوطلبانه و برخی کسبوکارها تشکیل شده است. اجرای گره یعنی داشتن نسخهٔ محلی و مستقلاً اعتبارسنجیشده از بلاکچین؛ دیگر لازم نیست به شخص ثالثی برای اعتبارسنجی تراکنش اعتماد کنید و شبکه را مقاومتر میکنید.
- نیازمند سامانهٔ همیشهمتصل است. تا اواخر ۲۰۱۶، گره با شاخص کامل حدود ۲ گیگابایت RAM و ۱۲۵ گیگابایت دیسک (با فضای رشد) لازم داشت و پهنای باند اینترنت نیز مصرف میکند؛ اگر سقف داده دارید یا اینترنت حجمی است، پهنای باند را محدود کنید یا گره نگذارید.
- بهطور پیشفرض کل بلاکچین (همهٔ تراکنشها از ۲۰۰۹) ذخیره میشود، حجم آن دهها گیگابایت است و همگامسازی اولیه چند روز تا چند هفته طول میکشد. تا پایان دانلود، گره نمیتواند تراکنش پردازش کند یا موجودی بهروز کند. با گزینهٔ prune میتوان بلاکهای قدیمی را دور ریخت، ولی کل داده همچنان ابتدا دانلود میشود.
- هزاران داوطلب گره اجرا میکنند؛ برخی روی Raspberry Pi (رایانهٔ ۳۵ دلاری) و بسیاری روی سرورهای اجارهای VPS یا ابری (۲۵ تا ۵۰ دلار در ماه).
- دلایل متداول اجرای گره: دسترسی برنامهنویسی (API) به شبکه و بلاکچین؛ ساخت برنامههایی که باید تراکنش را طبق قوانین اجماع اعتبارسنجی کنند؛ حمایت از بیتکوین؛ و اعتمادنکردن به هیچ طرف ثالث. نویسنده توصیه میکند توسعهدهندگان گره شخصی داشته باشند.
اولین اجرا و پیکربندی
- اولین اجرای
bitcoindخطا میدهد و میخواهد فایل پیکربندی با rpcuser و rpcpassword (و نامساویبودن این دو) بسازید؛ همچنین پیشنهاد رمز تصادفی و تنظیمalertnotifyمیدهد. این رمز دسترسی به رابط JSON-RPC را کنترل میکند. - فایل در
.bitcoin/bitcoin.confدر پوشهٔ خانگی ساخته میشود (با مجوز فقطخواندنی برای مالک). رمز نمونهٔ کتاب را هرگز استفاده نکنید. - بیش از ۱۰۰ گزینهٔ پیکربندی وجود دارد (
bitcoind --help) که میتوانند در فایل یا بهصورت پارامتر خط فرمان بیایند:
| گزینه | معنا |
|---|---|
alertnotify |
اجرای فرمان/اسکریپت برای ارسال هشدار اضطراری (معمولاً ایمیل) به مالک گره |
conf |
مکان جایگزین فایل پیکربندی (فقط بهعنوان پارامتر خط فرمان معنا دارد) |
datadir |
پوشه و فایلسیستم دادههای بلاکچین (پیشفرض .bitcoin) |
prune |
کاهش فضای دیسک به این تعداد مگابایت با حذف بلاکهای قدیمی |
txindex |
نگهداری شاخص همهٔ تراکنشها برای بازیابی هر تراکنش با شناسه |
maxconnections |
سقف اتصالهای ورودی؛ کاهش آن پهنای باند را کم میکند |
maxmempool |
سقف مگابایتی مخزن تراکنشهای تأییدنشده (mempool) |
maxreceivebuffer / maxsendbuffer |
سقف بافر حافظه برای هر اتصال (ضرایب ۱۰۰۰ بایت) |
minrelaytxfee |
حداقل کارمزد برای رلهکردن تراکنش؛ کمتر از آن مثل بدون کارمزد دیده میشود |
- ایندکس تراکنش و txindex: بهطور پیشفرض فقط تراکنشهای مرتبط با کیف پول کاربر شاخص میشوند. برای دسترسی به هر تراکنش دلخواه با
getrawtransactionبایدtxindex=1تنظیم شود؛ اگر بعداً فعال شود بایدbitcoindبا گزینهٔ-reindexراهاندازی مجدد شود و ساخت دوباره شاخص را صبر کرد. - مثال ۳-۱ (گره با شاخص کامل برای پشتیبان برنامه):
alertnotify،datadir=/lotsofspace/bitcoin،txindex=1و اعتبارنامههای RPC. - مثال ۳-۲ (گره کممنبع):
maxconnections=15،prune=5000،minrelaytxfee=0.0001،maxmempool=200،maxreceivebuffer=2500،maxsendbuffer=500بهعلاوهٔalertnotifyو اعتبارنامهها.
اجرا و پایش
bitcoind -printtoconsoleبرای اجرای پیشزمینه با خروجی در کنسول است (نمایش نسخهٔ OpenSSL، پوشهٔ داده، حداکثر ۱۲۵ اتصال، رشتههای تأیید اسکریپت، اتصال به پورت ۸۳۳۳ برای شبکهٔ P2P، سهم حافظهٔ پنهان برای شاخص بلاک، حالت زنجیره و مجموعهٔ UTXO در حافظه، و باز شدن LevelDB). با Ctrl-C میتوان قطع کرد. برای اجرای پسزمینهbitcoind -daemonبه کار میرود.bitcoin-cli getinfoپیشرفت و وضعیت را نشان میدهد؛ نمونه: نسخه 110200 (یعنی 0.11.2)، نسخهٔ پروتکل 70002، ارتفاع 396328 بلاک، ۱۵ اتصال، سختی (difficulty) حدود 1.2×10¹¹،testnet: falseوrelayfeeبرابر 0.0001.- برای اجرای دائمی باید بیتکوین را به اسکریپتهای راهاندازی سیستمعامل اضافه کرد؛ نمونهها در
contrib/init(با README) هستند.
رابط برنامهنویسی (API) در Bitcoin Core
- Bitcoin Core یک رابط JSON-RPC پیاده میکند که با ابزار کمکی
bitcoin-cliنیز قابل دسترسی است.bitcoin-cli helpفهرست دستورات (مثلaddnode،backupwallet،createmultisig،decoderawtransaction،verifymessage،walletpassphraseو …) را میدهد وbitcoin-cli help <command>توضیح، آرگومانها، خروجی و دو مثال (باbitcoin-cliو باcurl) ارائه میکند. - مثال تست:
bitcoin-cli getblockhash 1000باید روی هر گره همان هش را بدهد:00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09. این نشان میدهد گره درحال اجرا است، فرمان میپذیرد و دادهٔ بلاک ۱۰۰۰ را دارد.
گرفتن اطلاعات وضعیت: getinfo
خروجی JSON است (قالبی که برای همهٔ زبانها قابل مصرف و برای انسان خوانا است) و شامل نسخهٔ کلاینت (110200)، نسخهٔ پروتکل (70002)، ارتفاع بلاک (مثلاً 396367)، تعداد اتصال، سختی و تنظیمات است. رسیدن گره به ارتفاع فعلی میتواند بیش از یک روز طول بکشد و با همین دستور قابل پیگیری است.
کاوش و رمزگشایی تراکنشها: getrawtransaction و decoderawtransaction
- در فصل ۱، آلیس یک فنجان قهوه از کافهٔ باب خرید. شناسهٔ تراکنش (txid) آن
0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2است. getrawtransaction <txid>تراکنش سریالشده را بهصورت هگزادسیمال برمیگرداند وdecoderawtransaction <hex>آن را رمزگشایی میکند. در خروجی دیده میشود: اندازه ۲۵۸ بایت، نسخه ۱،locktimeصفر، یک ورودی (vin) که به خروجی صفرم تراکنش قبلی (شروع با7957a35fe) ارجاع میدهد و فیلدscriptSigوsequenceبرابر 4294967295 دارد.- دو خروجی (
vout) وجود دارد: ۰٫۰۱۵ بیتکوین (۱۵ میلیبیت) به آدرس کافه (1GdK9...) و ۰٫۰۸۴۵ به آدرس باقیمانده/پول خرد آلیس (1Cdid9...). نوع هر دوpubkeyhashاست و اسکریپت قفلOP_DUP OP_HASH160 ... OP_EQUALVERIFY OP_CHECKSIGاست. تراکنش با پیگیری ورودیها به تراکنشهای قبلی امکان دنبالکردن زنجیرهٔ مالکیت را میدهد. - نکتهٔ تراکنشپذیری (malleability): تا وقتی تراکنش در بلاک تأیید نشده، txid قطعی نیست و ممکن است تغییر کند؛ نبودن هش در بلاکچین ثابت نمیکند تراکنش پردازش نشده. پس از تأیید، txid تغییرناپذیر و معتبر است.
کاوش بلاکها: getblockhash و getblock
- بلاک را هم با ارتفاع و هم با هش میتوان ارجاع داد. تراکنش آلیس در بلاک 277316 است؛
getblockhash 277316هش0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4را میدهد وgetblock <hash>جزئیات را. - فیلدهای خروجی:
hash،confirmations(37371)،size(218629 بایت)،height،version(2)،merkleroot، فهرستtxشامل شناسهٔ تراکنشها،time،mediantime،nonce(924591752)،bits(1903a30c)،difficulty(حدود 1.18×10⁹)،chainwork،previousblockhashوnextblockhash. - این بلاک ۴۱۹ تراکنش دارد و تراکنش قهوهٔ آلیس شصتوچهارمین است.
استفادهٔ برنامهنویسانه از رابط Bitcoin Core
- JSON-RPC یعنی فراخوانی رویههای دوردست (روی گره) از طریق HTTP/HTTPS؛ مثال
curlیک درخواستjsonrpcبه127.0.0.1روی پورت ۸۳۳۲ (پورت RPC) با روشgetinfoمیفرستد. کتابخانههای HTTP عمومی کافیاند، اما کتابخانههای بستهبندی سادهتر هستند. کتابpython-bitcoinlibو کلاسRawProxyرا بهکار میبرد؛ نیازمند یک Bitcoin Core در حال اجرا است. - مثال ۳-۳: با
RawProxy().getinfo()فیلدblocksرا چاپ میکند (نمونه: 394075)؛ مثال سادهای از استفاده از کتابخانه. - مثال ۳-۴: تراکنش آلیس را با
getrawtransaction، رمزگشایی و برای هر خروجی آدرس و مقدار را چاپ میکند (دو خروجی ۰٫۰۱۵ و ۰٫۰۸۴۵). - مثال ۳-۵: بلاک 277316 را میگیرد، همهٔ ۴۱۹ تراکنش را با شناسه واکشی و رمزگشایی میکند و مجموع مقدار تمام خروجیها را حساب میکند؛ که برابر 10,322.07722534 BTC (شامل ۲۵ BTC پاداش بلاک و حدود ۰٫۰۹۰۹ کارمزد) است. این مثال با صدها فراخوانی RPC برتری رابط برنامهنویسی نسبت به دستیبودن را نشان میدهد. خواننده تشویق میشود عدد را با یک block explorer مقایسه کند، چون برخی explorerها مجموع را بدون پاداش و کارمزد گزارش میکنند.
کلاینتها، کتابخانهها و ابزارهای جایگزین
اکوسیستم پیادهسازیهای دیگر دارد که واسط بومی هر زبان را فراهم میکنند:
| زبان | پروژهها |
|---|---|
| C/C++ | Bitcoin Core، libbitcoin (ابزار، گره و کتابخانهٔ اجماع) و bitcoin explorer (خط فرمان آن)، picocoin (کلاینت سبک از Jeff Garzik) |
| JavaScript | bcoin (گره کامل ماژولار)، Bitcore (Bitpay)، BitcoinJS |
| Java | bitcoinj، Bits of Proof (BOP) |
| Python | python-bitcoinlib (Peter Todd)، pycoin (Richard Kiss)، pybitcointools (Vitalik Buterin) |
| Ruby | bitcoin-client |
| Go | btcd (گره کامل) |
| Rust | rust-bitcoin |
| C# | NBitcoin |
| Objective-C | CoreBitcoin |
کتابخانههای بسیار دیگری در زبانهای مختلف وجود دارند و پیوسته افزوده میشوند.
جمعبندی
Bitcoin Core پیادهسازی مرجع و متنباز بیتکوین است که گره کامل، موتور اعتبارسنجی و کیف پول مرجع را در بر دارد. در این فصل مراحل دریافت، انتخاب نسخه، پیکربندی و کامپایل آن، تنظیم bitcoin.conf (اعتبارنامههای RPC، txindex، prune و محدودکنندههای منابع) و اجرای گره دیده شد. سپس با رابط JSON-RPC (از طریق bitcoin-cli، curl و Python) دستورهایی مانند getinfo، getrawtransaction، decoderawtransaction، getblockhash و getblock را برای بررسی تراکنشها و بلاکها استفاده کردیم و فهرستی از کتابخانههای جایگزین دیدیم. فصل بعد به کلیدها و آدرسها میپردازد.
فصل ۴ — کلیدها و آدرسها (Keys, Addresses)
مقدمه
- بیتکوین بر رمزنگاری (cryptography) استوار است؛ واژهای یونانی به معنای «نوشتن پنهان». اما دانش رمزنگاری فقط رمزگذاری (encryption) نیست؛ برای اثبات آگاهی از یک راز بدون افشای آن (امضای دیجیتال) و اثبات اصالت داده (اثر انگشت دیجیتال) هم به کار میرود. نکتهٔ کنایهآمیز این است که رمزگذاری بخش مهمی از بیتکوین نیست: ارتباطات و دادههای تراکنش رمز نمیشوند و برای محافظت از وجوه هم نیازی به رمزشدن ندارند.
- مالکیت بیتکوین از طریق کلیدهای دیجیتال، آدرسها و امضاهای دیجیتال تعریف میشود. کلیدها در شبکه ذخیره نمیشوند؛ کاربر آنها را در فایل یا پایگاه دادهٔ سادهای به نام کیف پول نگه میدارد و کیف پول میتواند بدون اینترنت و بدون ارجاع به بلاکچین کلید بسازد.
- بیشتر تراکنشها برای ثبت در بلاکچین امضای دیجیتال معتبر میخواهند که فقط با کلید خصوصی ساخته میشود؛ پس هرکس نسخهای از کلید را داشته باشد، بیتکوین را کنترل میکند. امضایی که وجه را خرج میکند «شاهد» (witness) نیز نام دارد، یعنی دادهای که صحت مالکیت وجه خرجشده را تصدیق میکند.
- تشبیه: کلید عمومی مانند شمارهٔ حساب بانکی و کلید خصوصی مانند رمز یا امضای روی چک است. در پرداخت، کلید عمومی گیرنده با اثر انگشت دیجیتالش (یعنی آدرس بیتکوین) نمایش داده میشود؛ مثل نام ذینفع روی چک («در وجه …»). آدرس لزوماً از کلید عمومی نمیآید و میتواند نمایندهٔ یک اسکریپت باشد؛ همین انتزاع مقصد پرداخت را انعطافپذیر میکند، مثل چک کاغذی که میتواند به حساب شخص، شرکت یا نقد پرداخت شود. آدرس تنها بخشی از کلیدهاست که کاربر معمولاً میبیند.
- ترتیب فصل: مبانی رمزنگاری، تولید و ذخیره و مدیریت کلید، قالبهای کدگذاری، و سپس موضوعات پیشرفته: آدرسهای vanity، چندامضایی و اسکریپتی و کیف پولهای کاغذی.
رمزنگاری کلید عمومی و ارزهای رمزنگاریشده
- رمزنگاری کلید عمومی در دهه ۱۹۷۰ ابداع شد و زیربنای امنیت رایانه و اطلاعات است. توابع ریاضی مناسبی مثل توانرسانی اعداد اول و ضرب روی منحنی بیضوی کشف شدهاند که عملاً برگشتناپذیرند: در یک جهت آسان و در جهت مخالف غیرعملیاند. بیتکوین از ضرب منحنی بیضوی استفاده میکند.
- جفت کلید شامل کلید خصوصی و کلید عمومی یکتای مشتقشده از آن است. کلید عمومی برای دریافت وجه و کلید خصوصی برای امضای تراکنش خرج استفاده میشود. امضا را میتوان بدون افشای کلید خصوصی در برابر کلید عمومی صحتسنجی کرد.
- هنگام خرج، مالک فعلی کلید عمومی و امضایی (که هر بار متفاوت است ولی از همان کلید خصوصی ساخته میشود) در تراکنش ارائه میکند و همهٔ شبکه میتواند اعتبار آن را تأیید کند.
- در بسیاری از کیف پولها کلید خصوصی و عمومی با هم ذخیره میشوند، ولی چون کلید عمومی از خصوصی قابل محاسبه است، ذخیرهٔ کلید خصوصی تنها هم ممکن است.
کلیدهای خصوصی و عمومی
زنجیرهٔ مشتقگیری: کلید خصوصی (k) که عددی تصادفی است ← با ضرب منحنی بیضوی (تابع یکطرفه) به کلید عمومی (K) ← با تابع هش یکطرفه به آدرس بیتکوین (A).
چرا رمزنگاری نامتقارن؟ برای «رمز کردن» تراکنشها نیست؛ ویژگی مفید آن توانایی تولید امضای دیجیتال است. کلید خصوصی بر اثر انگشت تراکنش اعمال میشود و امضای عددی میدهد که فقط دارندهٔ کلید خصوصی میتواند بسازد، اما هر کس با کلید عمومی و اثر انگشت میتواند آن را تأیید کند. بنابراین همه میتوانند هر امضا را راستیآزمایی کنند ولی فقط مالکان کلید میتوانند امضای معتبر تولید کنند.
کلیدهای خصوصی
- کلید خصوصی صرفاً یک عدد تصادفی است و ریشهٔ کنترل کاربر بر تمام وجوه مرتبط با آدرسهای مربوط به آن است. باید همیشه محرمانه بماند (افشا یعنی واگذاری کنترل) و نیز پشتیبانگیری شود، چون گمشدنش جبرانناپذیر است و وجوه برای همیشه از دست میروند.
- حتی میتوان با یک سکه و کاغذ، ۲۵۶ بار شیر یا خط انداخت و ارقام باینری کلید خصوصی را ساخت.
تولید کلید از عدد تصادفی
- مهمترین گام، منبع امن آنتروپی (تصادفی بودن) است. ساختن کلید یعنی «عددی بین ۱ و ۲²⁵⁶ انتخاب کن»؛ روش انتخاب مهم نیست مگر آنکه قابل پیشبینی یا تکرار باشد. نرمافزار بیتکوین از مولد اعداد تصادفی سیستمعامل ۲۵۶ بیت آنتروپی میگیرد (به همین دلیل گاهی از شما میخواهند ماوس را تکان دهید).
- دقیقتر، کلید میتواند هر عدد بین ۱ و n−1 باشد، که n ثابتی ≈ 1٫158×10⁷⁷ (کمی کمتر از 2²⁵⁶) و مرتبهٔ منحنی بیضوی بیتکوین است. روش معمول: رشتهای بزرگ از بیتهای تصادفی با منبع امن را به SHA256 میدهند تا عدد ۲۵۶ بیتی بدهد؛ اگر کمتر از n−1 بود، پذیرفته میشود، وگرنه دوباره تلاش میشود.
- هشدار: کد تولید عدد تصادفی خود ننویسید و از مولدهای ساده زبان برنامهنویسی استفاده نکنید؛ فقط از CSPRNG (مولد شبهتصادفی امن رمزنگاری) با بذر کافی استفاده کنید.
- نمونه کلید خصوصی (هگز، ۶۴ رقم):
1E99423A4ED27608A15A2616A2B0E9E52CED330AC530EDCC32C8FFC6A526AEDD. فضای کلید حدود 10⁷⁷ است؛ برای مقایسه، تعداد اتمهای جهان قابل مشاهده حدود 10⁸⁰ برآورد میشود. - در Bitcoin Core،
getnewaddressکلید میسازد (فقط آدرس را نشان میدهد) وdumpprivkey <address>کلید خصوصی را در قالب WIF (Wallet Import Format) نشان میدهد (مثال:KxFC1jm...). این دستور کلید را از کلید عمومی استخراج نمیکند (غیرممکن است)، بلکه کلیدی را که کیف پول از قبل دارد افشا میکند. با ابزار Bitcoin Explorer نیز میتوان زنجیرهٔbx seed | bx ec-new | bx ec-to-wifرا اجرا کرد (نتیجه: کلیدی با پیشوند5).
کلیدهای عمومی
- کلید عمومی با ضرب منحنی بیضوی ساخته میشود: K = k × G، که k کلید خصوصی، G «نقطهٔ مولد» (generator point) ثابت و K نقطهای روی منحنی است. معکوس آن، «لگاریتم گسسته»، بهاندازهٔ جستجوی فراگیر همهٔ مقادیر k دشوار است. این تابع در اصطلاح رمزنگاران «تابع درِپشتی» (trap door) است: ضرب آسان، «تقسیم» ناممکن.
توضیح رمزنگاری منحنی بیضوی (ECC)
- ECC نوعی رمزنگاری نامتقارن مبتنی بر مسئلهٔ لگاریتم گسسته است که با جمع و ضرب روی نقاط منحنی بیضوی بیان میشود.
- بیتکوین منحنی مشخصی به نام secp256k1 (استاندارد تعریفشده توسط NIST) را بهکار میبرد؛ معادلهٔ آن y² = x³ + 7 روی میدان متناهی از مرتبهٔ اول p است که p = 2²⁵⁶ − 2³² − 2⁹ − 2⁸ − 2⁷ − 2⁶ − 2⁴ − 1 (عدد اولی بسیار بزرگ). چون روی میدان متناهی است، شکل منحنی بهصورت الگوی نقاطی پراکنده دیده میشود، هرچند ریاضیات آن همان منحنی روی اعداد حقیقی است (شکل ۴-۳ یک منحنی روی میدان با p=17 را نشان میدهد).
- مثال ۴-۱ در پایتون نشان میدهد نقطهای مشخص روی منحنی است با بررسی اینکه
(x**3 + 7 - y**2) % pصفر میشود. - جمع نقاط: برای دو نقطه P1 و P2 خطی که از آنها میگذرد منحنی را در نقطهٔ سومی P3′ قطع میکند و قرینهٔ آن نسبت به محور x، حاصلجمع P3 = P1 + P2 است. برای P1 = P2 خط مماس به کار میرود (حساب دیفرانسیل). اگر مماس عمودی باشد (x یکسان و y متفاوت) حاصل نقطهٔ بینهایت (point at infinity) است که نقش صفر را دارد: P + ∞ = P. جمع شرکتپذیر است.
- ضرب: kP یعنی k بار جمع P با خودش. برای محاسبهٔ K = k·G، همان جمعهای مکرر نقطهٔ مولد (شکل ۴-۴: G، 2G، 4G و …). بیشتر پیادهسازیها از کتابخانهٔ OpenSSL (تابع
EC_POINT_mul()) استفاده میکنند. - چون G برای همهٔ کاربران ثابت است، k × G همیشه یک K یکتا میدهد، ولی فقط از k به K میتوان رفت، و به همین دلیل آدرس را میتوان با دیگران به اشتراک گذاشت.
- برای کلید نمونه، K = (x, y) با
x = F028892B...DC341Aوy = 07CF33DA...2E505BDBبه دست میآید.
آدرسهای بیتکوین
- آدرس رشتهای از ارقام و حروف است که میتوان به هرکسی که میخواهد پول بفرستد داد. آدرسهای مشتقشده از کلید عمومی با رقم «1» شروع میشوند (مثلاً
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy). در تراکنش، آدرس بهعنوان «گیرنده» ظاهر میشود؛ مثل ذینفع روی چک. - آدرس با هش یکطرفه از کلید عمومی مشتق میشود. الگوریتمها SHA256 و سپس RIPEMD160 هستند: A = RIPEMD160(SHA256(K)) که خروجی ۱۶۰ بیتی (۲۰ بایتی) است. آدرس با کلید عمومی یکی نیست.
- هشهای رمزنگاری در بیتکوین در آدرسها، آدرسهای اسکریپتی و اثبات کار استفاده میشوند.
- آدرسها تقریباً همیشه با Base58Check کدگذاری میشوند (شکل ۴-۵ فرایند تبدیل کلید عمومی به آدرس را نشان میدهد).
کدگذاری Base58 و Base58Check
- برای نمایش فشردهٔ اعداد بزرگ از مبناهای بالاتر از ۱۰ استفاده میشود: هگزادسیمال (۱۶)، Base64 (۲۶ حرف کوچک + ۲۶ بزرگ + ۱۰ رقم + «+» و «/» که برای پیوست ایمیل به کار میرود) و Base58 که برای بیتکوین ساخته شد. Base58 زیرمجموعهٔ Base64 است که نویسههای پرابهام را حذف میکند:
0(صفر)،O(o بزرگ)،l(L کوچک)،I(i بزرگ) و علائم+و/. - الفبای Base58:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz. - Base58Check نسخهای با کد تشخیص خطای داخلی است: چهار بایت checksum به انتهای داده افزوده میشود و رمزگشا آن را مجدداً حساب و مقایسه میکند. این از پذیرش آدرس اشتباهتایپشده و از دست رفتن وجه جلوگیری میکند. همچنین برای کلیدهای خصوصی، کلیدهای رمزشده و هش اسکریپت بهکار میرود.
- مراحل کدگذاری:
- افزودن بایت نسخه (version prefix) به ابتدای داده (مثلاً
0x00برای آدرس و0x80برای کلید خصوصی). - محاسبهٔ checksum = SHA256(SHA256(prefix + data)) و برداشتن ۴ بایت اول.
- الحاق به انتها و کدگذاری با الفبای Base58 (شکل ۴-۶).
- افزودن بایت نسخه (version prefix) به ابتدای داده (مثلاً
- بایت نسخه سبب میشود نتیجه با نویسههای مشخص شروع شود تا انسان نوع داده را تشخیص دهد (آدرس با 1 و WIF با 5). جدول ۴-۱:
| نوع | بایت نسخه (hex) | پیشوند Base58 |
|---|---|---|
| آدرس بیتکوین (P2PKH) | 0x00 |
1 |
| آدرس Pay-to-Script-Hash | 0x05 |
3 |
| آدرس Testnet | 0x6F |
m یا n |
| کلید خصوصی WIF | 0x80 |
5، K یا L |
| کلید خصوصی رمزشده BIP-38 | 0x0142 |
6P |
| کلید عمومی توسعهیافته BIP-32 | 0x0488B21E |
xpub |
- مثال ۴-۳ (C++ با libbitcoin): کل مسیر را گامبهگام نشان میدهد: کلید خصوصی ثابت ← کلید عمومی (
secret_to_public_key) ← هشbitcoin_short_hash(۲۰ بایت) ← بافر ۲۵ بایتی [نسخه:۱ + هش:۲۰ + checksum:۴] ←encode_base58. با کلید ثابت مثال، کلید عمومی0202a406...47aaو آدرس1PRTTaJesdNovgne6Ehcdu1fpEdX7913CKتولید میشود (مثال ۴-۴: کامپایل باg++و اجرا).
قالبهای کلید
قالبهای کلید خصوصی
همگی همان عدد ۲۵۶ بیتی را با نمایشهای متفاوت نشان میدهند (جدول ۴-۲):
| نوع | پیشوند | توضیح |
|---|---|---|
| Raw | — | ۳۲ بایت |
| Hex | — | ۶۴ رقم هگزادسیمال |
| WIF | 5 |
Base58Check با بایت نسخه ۱۲۸ و checksum ۳۲ بیتی |
| WIF-compressed | K یا L |
مانند WIF با پسوند 0x01 پیش از کدگذاری |
- مثال یک کلید (جدول ۴-۳): hex =
1e99423a...a526aedd؛ WIF =5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn؛ WIF-compressed =KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ. - ابزار Bitcoin Explorer:
bx wif-to-ecهر دو WIF را به همان hex برمیگرداند؛bx base58check-decodeسه جزء checksum، payload و version (۱۲۸) را نشان میدهد و در حالت فشرده payload یک پسوند01اضافه دارد؛bx base58check-encode <hex> --version 128عکس آن است، و برای فرم فشرده باید ابتدا01به hex الحاق شود.
قالبهای کلید عمومی
- کلید عمومی نقطه (x, y) است. شکل غیرفشرده با پیشوند
04و سپس x و y (هرکدام ۲۵۶ بیت) نمایش داده میشود: مجموعاً ۵۲۰ بیت (۱۳۰ رقم hex). - کلید عمومی فشرده (compressed): برای کاهش اندازهٔ تراکنشها و فضای ذخیرهسازی گرهها معرفی شد؛ هر کلید ۵۲۰ بیتی در هر تراکنش حجم قابلتوجهی میسازد. چون y از معادلهٔ منحنی (y² = x³ + 7 mod p) قابل محاسبه است، فقط x ذخیره میشود؛ ولی چون ریشهٔ دوم دو علامت دارد (منحنی نسبت به محور x متقارن است)، باید زوج یا فرد بودن y نیز ذخیره شود: پیشوند
02برای y زوج و03برای y فرد. نتیجه ۲۶۴ بیت (۶۶ رقم hex) و کاهش تقریباً ۵۰٪ است. نمونه:03F028892BAD...DC341A. - نکتهٔ مهم: کلید فشرده و غیرفشرده از یک کلید خصوصی ساخته میشوند ولی با هشکردن آدرسهای متفاوت میدهند. کیف پولهای جدید از کلید فشرده استفاده میکنند و باید با تراکنشهای کیفپولهای قدیمی سازگار باشند. هنگام وارد کردن (import) کلید باید بدانند کدام آدرس را در بلاکچین جستجو کنند؛ برای همین قالب WIF تفاوت دارد.
کلیدهای خصوصی «فشرده» (اصطلاح نادرست)
- عبارت «کلید خصوصی فشرده» اشتباه است: کلید خصوصی خودش فشرده نمیشود. WIF-compressed در واقع یک بایت بلندتر است (پسوند
01) و فقط میگوید «از این کلید فقط کلید عمومی فشرده (و آدرس متناظر) استخراج شود». بهتر است فقط بگوییم «WIF-compressed». - با افزودن یک بایت، نخستین نویسهٔ Base58 از
5بهKیاLتغییر میکند؛ مانند اینکه ۱۰۰ از ۹۹ یک رقم بلندتر است و با ۱ شروع میشود. جدول ۴-۴: hex ←...AEDDو Hex-compressed ←...AEDD01. - کیف پول جدید فقط WIF-compressed (K/L) صادر میکند و کیف پول قدیمی فقط WIF (5)؛ هدف این است که کیف پول دریافتکننده بداند کدام نوع کلید عمومی و آدرس را جستجو کند.
پیادهسازی کلید و آدرس در پایتون
- مثال ۴-۵ و ۴-۶ (کتابخانهٔ pybitcointools): کلید تصادفی با
random_key()میگیرد و بررسی میکند0 < key < N؛ سپس نمایش hex و دهدهی، WIF و WIF-compressed (با افزودن01)، نقطهٔ عمومی باfast_multiply(G, k)، قالب hex با پیشوند04، فشردهسازی با انتخاب02/03بر اساس زوج/فرد بودن y، و دو آدرس متفاوت (غیرفشرده1thMirt...و فشرده14cxpo3...) برای همان کلید را نمایش میدهد. - مثال ۴-۷ و ۴-۸ (کتابخانهٔ ecdsa بدون ابزار خاص بیتکوین): ثابتهای secp256k1 (p، مرتبه، a = 0، b = 7 و مختصات G) را تعریف میکند، راز ۲۵۶ بیتی را با
os.urandom(32)میگیرد، نقطه را باsecret * generatorحساب میکند و کلید عمومی فشرده را میسازد (02/03+ x). یادداشت میگویدos.urandomاز/dev/urandomیاCryptGenRandom()در ویندوز میگیرد، اما برای کد تولیدی کافی نیست.
کلیدها و آدرسهای پیشرفته
کلیدهای خصوصی رمزشده (BIP-38)
- محرمانگی کلید با نیاز به پشتیبانگیری و انتقال بین کیف پولها (برای ارتقای نرمافزار) در تضاد است. BIP-38 استاندارد قابل حمل برای رمزکردن کلید خصوصی با عبارت عبور (passphrase) و کدگذاری Base58Check است، با استفاده از AES.
- ورودی معمولاً WIF با پیشوند
5و خروجی کلید رمزشده با پیشوند6Pاست؛ برای بازگرداندن به WIF به عبارت عبور نیاز است. بسیاری از کیف پولها این قالب را میشناسند و رمز را میپرسند؛ ابزارهایی مثل bitaddress.org برای رمزگشایی هم وجود دارد. - رایجترین کاربرد: کیف پول کاغذی برای ذخیرهسازی سرد (cold storage) با عبارت عبور قوی. نمونه (جدول ۴-۵): کلید
5J3mBb...Jcnبا عبارتMyTestPassphraseبه6PRTHL6mWa48xSopbU1cKrVjpKbBZxcLRRCdctLJ3z5yxE87MobKoXdTsJرمز میشود.
آدرسهای Pay-to-Script-Hash (P2SH) و چندامضایی
- آدرسهای سنتی با
1(P2PKH) از کلید عمومی مشتق میشوند و خرجشان با امضای کلید خصوصی و ارائهٔ کلید عمومی ممکن است. آدرسهای با3از نوع P2SH هستند (که گاهی اشتباهاً «آدرس چندامضایی» خوانده میشوند): گیرنده هش یک اسکریپت است و نه کلید عمومی. این قابلیت در ژانویه ۲۰۱۲ با BIP-16 معرفی شد و شرایط خرج هنگام ساخت آدرس در اسکریپت تعیین میشود و روی همهٔ ورودیهای آن آدرس اعمال میگردد. - محاسبه: script hash = RIPEMD160(SHA256(script)) سپس Base58Check با بایت نسخه ۵ که آدرس را با
3شروع میکند. مثال:3F6i6kwkevjR7AsAd4te2YB2zZyASEm1HMبا زنجیرهٔ دستوراتbx script-encode | bx sha256 | bx ripemd160 | bx base58check-encode --version 5. - P2SH لزوماً چندامضایی نیست؛ رایجترین کاربردش اسکریپت چندامضایی (multisig) است، ولی اسکریپتهای دیگر را هم میتوان با آن بست.
- چندامضایی M-of-N: M امضا (آستانه) از مجموع N کلید لازم است (M ≤ N). مثالهای کتاب: باب (صاحب کافه) با حساب مشترک ۱ از ۲ با همسرش، و گوپش (طراح وب) با حساب ۲ از ۳ برای شرکایش تا بدون حداقل دو امضا وجهی خرج نشود. ساخت تراکنش خرج از این آدرسها در فصل ۶ بررسی میشود.
آدرسهای Vanity
- آدرسهای vanity آدرسهای معتبری هستند که الگوی قابلخواندن دارند، مانند
1LoveBPzzD72PUXLzCkYAtGFYmK5vYNR33که با «Love» شروع میشود. ساختنشان نیازمند جستجوی brute-force است: انتخاب کلید تصادفی، مشتقگیری کلید عمومی و آدرس، بررسی تطابق با الگو، و تکرار میلیاردها بار. امنیتی کمتر یا بیشتر از آدرسهای معمولی ندارند؛ پیدا کردن کلید خصوصی آنها هم سادهتر نیست. - مثال اوجنیا (مدیر خیریهٔ کودکان در فیلیپین از فصل ۱) که آدرسی با «1Kids» میخواهد. آدرسها اعدادی در مبنای ۵۸ هستند؛ بازهٔ
1Kids111...1تا1Kidszzz...zحدود 58⁹ ≈ 1٫۴×10⁵¹ آدرس دارد. هر نویسهٔ اضافه، دشواری را ۵۸ برابر میکند. در جدول ۴-۷ (رایانهٔ رومیزی با حدود ۱۰۰٬۰۰۰ کلید در ثانیه):
| طول الگو | نمونه | فراوانی | زمان متوسط |
|---|---|---|---|
| ۱ | 1K |
۱ در ۵۸ | کمتر از ۱ میلیثانیه |
| ۲ | 1Ki |
۱ در ۳٬۳۶۴ | ۵۰ میلیثانیه |
| ۳ | 1Kid |
۱ در ۱۹۵ هزار | کمتر از ۲ ثانیه |
| ۴ | 1Kids |
۱ در ۱۱ میلیون | ۱ دقیقه |
| ۵ | 1KidsC |
۱ در ۶۵۶ میلیون | ۱ ساعت |
| ۶ | 1KidsCh |
۱ در ۳۸ میلیارد | ۲ روز |
| ۷ | 1KidsCha |
۱ در ۲٫۲ تریلیون | ۳ تا ۴ ماه |
| ۸ | 1KidsChar |
۱ در ۱۲۸ تریلیون | ۱۳ تا ۱۸ سال |
| ۹ | 1KidsChari |
۱ در ۷ کوادریلیون | ۸۰۰ سال |
| ۱۰ | 1KidsCharit |
۱ در ۴۰۰ کوادریلیون | ۴۶٬۰۰۰ سال |
| ۱۱ | 1KidsCharity |
۱ در ۲۳ کوینتیلیون | ۲٫۵ میلیون سال |
- الگوهای بلندتر از ۷ نویسه معمولاً با سختافزار تخصصی (چند GPU، گاهی دستگاههای ماینینگ بازنشسته) پیدا میشوند؛ GPU چند مرتبه سریعتر از CPU است. گزینهٔ دیگر استخرهای vanity (مثل Vanity Pool) است؛ اوجنیا با حدود ۰٫۰۱ بیتکوین (حدود ۵ دلار آن زمان) میتواند الگوی ۷ نویسهای را در چند ساعت بگیرد.
- مثال ۴-۹ و ۴-۱۰ (C++، vanity miner): حلقهای که کلید تصادفی تولید میکند، آدرس میسازد و با رشتهٔ
1kid(بدون حساسیت به حروف) مقایسه میکند؛ در یک اجرا حدود ۹ ثانیه طول کشید (نمونهها:1KiDzkG4...و1Kidxr3w...). هشدار: مولد اعداد تصادفی آن برای تولید کلید واقعی کافی نیست. - امنیت vanity: شمشیر دولبه است. آدرس متمایز تعویض مخرب آدرس را برای مهاجم سختتر میکند، اما هر کسی میتواند آدرسی شبیه یک آدرس تصادفی دیگر بسازد. جدول ۴-۸: برای آدرس
1J7mdg5rbQ...مهاجم میتواند آدرسهایی با ۴، ۵ و ۶ نویسهٔ مشابه بسازد. وقتی اوجنیا آدرسی مثل1Kids33q44er...را منتشر کند، کاربر احتمالاً الگو را بهعلاوهٔ چند نویسهٔ بعدی بررسی میکند؛ مهاجم باید دستکم ۶ نویسه را تطبیق دهد، یعنی ۵۸×۵۸ = ۳٬۳۶۴ برابر تلاش بیشتر از اوجنیا. هر چه هزینهٔ اوجنیا برای vanity بیشتر باشد، هزینهٔ مهاجم بهطور نمایی بزرگتر میشود (مثلاً vanity هشتنویسه مهاجم را به دهنویسه میرساند که روی رایانهٔ شخصی ناممکن است).
کیف پولهای کاغذی
- کیف پول کاغذی کلید خصوصی چاپشده روی کاغذ است (معمولاً با آدرس متناظر برای راحتی؛ لازم نیست چون از کلید قابل محاسبه است). هم برای پشتیبان (در برابر خرابی دیسک، سرقت یا حذف) و هم برای ذخیرهسازی سرد کاربرد دارد، بهشرط اینکه کلید آفلاین تولید شده و هرگز روی رایانهٔ آنلاین ذخیره نشده باشد.
- سادهترین شکل (جدول ۴-۹) آدرس عمومی و کلید خصوصی WIF است. میتوان با مولد جاوااسکریپتی سمت کلاینت bitaddress.org آن را ساخت: صفحه را ذخیره، از اینترنت قطع، بهتر است با سیستمعامل تمیز (مثلاً لینوکس زنده از CD) اجرا و با چاپگر USB (نه بیسیم) چاپ کنید و در گاوصندوق نگه دارید و با ارسال وجه به آدرس آن «ذخیرهٔ سرد» بسازید.
- ضعف: کاغذ میتواند دزدیده یا عکسبرداری شود. راهحل پیشرفتهتر استفاده از کلید رمزشدهٔ BIP-38 است (شکل ۴-۹)، که بدون عبارت عبور بیفایده است.
- هشدار برداشت: گرچه میتوان چند بار به کیف پول کاغذی واریز کرد، باید همهٔ موجودی را فقط یک بار برداشت کرد؛ چون برخی کیف پولها هنگام برداشت جزئی آدرس باقیمانده میسازند و اگر رایانهای که تراکنش را امضا میکند آلوده باشد کلید فاش میشود. اگر فقط مقدار کمی لازم است، بقیه را در همان تراکنش به کیف پول کاغذی جدید بفرستید.
- طراحیهای متنوعی وجود دارد: هدیهای با تمهای فصلی، گاوصندوق بانکی با کلید پنهان زیر برچسب خراشپذیر یا فویل ضدتقلب (شکلهای ۴-۱۰ و ۴-۱۱ از bitcoinpaperwallet.com)، و طرحهایی با «استاب» جداشدنی که نسخههای اضافی کلید و آدرس را برای محافظت در برابر آتش و سیل دارند (شکل ۴-۱۲).
جمعبندی
مالکیت در بیتکوین بر جفتکلید استوار است: کلید خصوصی یک عدد تصادفی ۲۵۶ بیتی (کمتر از مرتبهٔ n منحنی secp256k1) است که با ضرب منحنی بیضوی K = k·G به کلید عمومی و با SHA256 و RIPEMD160 و Base58Check به آدرس تبدیل میشود؛ مسیر برگشتی ناممکن است. آدرسها با بایت نسخه و checksum چهاربایتی کدگذاری میشوند (1، 3، 5/K/L، 6P، xpub) و کلید عمومی میتواند فشرده (02/03) یا غیرفشرده (04) باشد که دو آدرس متفاوت از یک کلید خصوصی میدهد و WIF-compressed این تفاوت را مشخص میکند. موضوعات پیشرفته شامل BIP-38 (کلید رمزشده)، P2SH و چندامضایی M-of-N (BIP-16)، آدرسهای vanity (با هزینهٔ نمایی بر پایهٔ ۵۸) و کیف پولهای کاغذی برای ذخیرهٔ سرد بود. پایهای که فصل بعد (کیف پولها، BIP-32/39) روی آن ساخته میشود.
فصل ۵ — کیفپولها (Wallets)
«کیف پول» در بیتکوین یعنی چه؟
واژهٔ «کیف پول» (wallet) در دنیای بیتکوین چند معنا دارد:
- در سطح بالا: برنامهای که رابط اصلی کاربر است؛ دسترسی به پول او را کنترل میکند، کلیدها و آدرسها را مدیریت میکند، موجودی را دنبال میکند و تراکنش میسازد و امضا میکند.
- از دید برنامهنویس (معنای مورد بحث این فصل): ساختار دادهٔ ذخیره و مدیریت کلیدهای کاربر؛ یعنی ظرفی برای کلیدهای خصوصی که معمولاً به شکل فایل ساختاریافته یا یک پایگاه دادهٔ ساده پیاده میشود.
مروری بر فناوری کیف پول
کیف پول کلید دارد، نه سکه
یک تصور غلط رایج این است که کیف پول بیتکوین «حاوی بیتکوین» است. در واقع کیف پول فقط کلید نگه میدارد؛ «سکهها» در بلاکچین و به شکل خروجیهای تراکنش (در اصطلاح vout یا txout، همان UTXOها) ثبت میشوند. کاربر با امضای تراکنش بهوسیلهٔ کلیدهای کیف پولش ثابت میکند مالک آن خروجیهاست. پس کیف پول عملاً یک حلقهکلید (keychain) است که جفتکلیدهای خصوصی/عمومی در آن قرار دارد.
دو دستهٔ اصلی
دستهبندی بر اساس این است که کلیدهای داخل کیف پول به هم مربوطاند یا نه:
| نوع | ویژگی | توضیح |
|---|---|---|
| غیرقطعی (nondeterministic) | هر کلید مستقل و با عدد تصادفی ساخته میشود | به آن JBOK («فقط یک مشت کلید»، Just a Bunch Of Keys) یا کیف پول «نوع ۰» هم میگویند |
| قطعی (deterministic) | همهٔ کلیدها از یک کلید اصلی به نام بذر (seed) مشتق میشوند | با داشتن بذر میتوان همهٔ کلیدها را دوباره ساخت؛ رایجترین روش مشتقگیری ساختار درختی است و کیف پول HD (سلسلهمراتبی قطعی) نام دارد |
برای راحتی کاربر، بذر کیف پولهای قطعی به شکل واژههای انگلیسی کدگذاری میشود که به آن عبارت یادآور (mnemonic) میگویند.
کیفپولهای غیرقطعی (تصادفی)
نخستین کیف پول بیتکوین (که امروز Bitcoin Core نام دارد) مجموعهای از کلیدهای خصوصی تصادفی بود. کلاینت اولیه هنگام راهاندازی ۱۰۰ کلید تصادفی از پیش میساخت و هر کلید را فقط یک بار به کار میبرد و در صورت نیاز کلید بیشتری تولید میکرد. این الگو رو به منسوخشدن است، چون:
- مدیریت، پشتیبانگیری و وارد کردن (import) آن دشوار است؛ هر کلید باید جداگانه پشتیبانگیری شود، وگرنه اگر کیف پول در دسترس نباشد وجوه کنترلشده با آن کلید برای همیشه از دست میرود. پس پشتیبانگیری مکرر لازم است.
- با اصل عدم استفادهٔ مجدد از آدرس (هر آدرس فقط برای یک تراکنش) در تضاد است؛ چون رعایت آن یعنی کلیدهای بسیار زیاد. استفادهٔ مجدد از آدرس، چند تراکنش و آدرس را به هم پیوند میدهد و حریم خصوصی را کاهش میدهد.
- با اینکه Bitcoin Core هنوز کیف پول نوع ۰ دارد، خود توسعهدهندگان استفاده از آن را توصیه نمیکنند.
توصیه: کیف پول غیرقطعی فقط برای آزمایشهای ساده؛ برای استفادهٔ واقعی، کیف پول HD مبتنی بر استانداردهای صنعتی با بذر mnemonic.
کیفپولهای قطعی (بذردار)
در این کیف پولها همهٔ کلیدهای خصوصی با یک تابع هش یکطرفه از یک بذر مشترک مشتق میشوند. بذر عددی تصادفی است که با دادههای دیگر مانند شمارهٔ ایندکس یا «chain code» ترکیب میشود. مزایا:
- بذر برای بازیابی همهٔ کلیدهای مشتقشده کافی است؛ پس یک پشتیبان در لحظهٔ ساخت بس است.
- بذر برای export/import کیف پول هم کفایت میکند و انتقال همهٔ کلیدها بین پیادهسازیهای مختلف کیف پول را آسان میکند.
کیفپولهای HD (BIP-32 و BIP-44)
پیشرفتهترین شکل کیف پول قطعی، کیف پول HD است که در استاندارد BIP-32 تعریف شده است. کلیدها در یک درخت قرار میگیرند: هر کلید والد میتواند دنبالهای از فرزندان بسازد، هر فرزند دنبالهای از نوهها و همینطور تا عمق نامحدود. دو مزیت عمدهٔ این ساختار نسبت به کلیدهای تصادفی:
- معنای سازمانی: شاخهها میتوانند نقش داشته باشند؛ مثلاً یک شاخه برای دریافت پرداختها و شاخهای دیگر برای دریافت باقیمانده (change) تراکنشهای خروجی. در محیط سازمانی هم میتوان شاخهها را به بخشها، شرکتهای تابعه، وظایف خاص یا دستههای حسابداری اختصاص داد.
- ساخت کلید عمومی بدون کلید خصوصی: میتوان دنبالهای از کلیدهای عمومی را بدون دسترسی به کلیدهای خصوصی متناظر تولید کرد. بنابراین کیف پول را میتوان روی سرور ناامن یا در حالت «فقط دریافت» به کار برد؛ برای هر تراکنش کلید عمومی جدید صادر میشود، بیآنکه کلیدها از پیش ساخته و بارگذاری شده باشند، و سرور کلیدی برای خرجکردن وجوه ندارد.
بذر و عبارتهای یادآور (BIP-39)
HD ترکیب قدرتمندی برای مدیریت کلیدهاست و وقتی با روش استانداردِ ساخت بذر از دنبالهٔ واژههای انگلیسی همراه شود حتی کاربردیتر میشود، چون این واژهها آسان نوشته، منتقل و بین کیف پولها وارد میشوند. این استاندارد BIP-39 است و امروزه بیشتر کیف پولهای بیتکوین (و ارزهای دیگر) از آن پشتیبانی میکنند. مقایسهٔ کتاب: رشتهٔ هگزادسیمال 0C1E24E5917779D297E14D45F14E1A1A در برابر دوازده واژهٔ army van defense carry jealous true garbage claim echo media make crunch؛ دوم برای رونویسی روی کاغذ، خواندن بدون خطا و انتقال بسیار آسانتر است.
بهترین شیوهها در کیف پول
با بلوغ فناوری، چند استاندارد همپیوند بهصورت عملی استاندارد صنعت شدهاند:
- BIP-39: کلمات یادآور
- BIP-32: کیف پول HD
- BIP-43: ساختار چندمنظورهٔ HD
- BIP-44: کیف پول چندارزی و چندحسابی
ممکن است در آینده تغییر کنند یا منسوخ شوند، اما فعلاً استاندارد عملی هستند و باعث همکاریپذیری (interoperability) میشوند: کاربر میتواند mnemonic ساختهشده در یک کیف پول را در کیف پول دیگر وارد کند و همهٔ تراکنشها، کلیدها و آدرسها را بازیابی کند. نمونههای نرمافزاری که کتاب نام میبرد: Breadwallet، Copay، Multibit HD و Mycelium؛ و سختافزاری: Keepkey، Ledger و Trezor.
اگر کیف پول بیتکوین پیادهسازی میکنید، باید HD باشد، بذرش بهصورت mnemonic برای پشتیبانگیری کدگذاری شود و از BIP-32، BIP-39، BIP-43 و BIP-44 پیروی کند.
استفاده از یک کیف پول: داستان گابریل
کتاب شخصیت گابریل را معرفی میکند: نوجوانی کارآفرین در ریو دو ژانیرو که وبفروشگاه کوچکی برای تیشرت، لیوان و استیکرهای بیتکوینی دارد. او برای مدیریت امن پولش از کیف پول سختافزاری Trezor استفاده میکند: دستگاه سادهای با رابط USB و دو دکمه که کلیدها (در قالب کیف پول HD) را نگه میدارد و تراکنشها را امضا میکند. چون Trezor همهٔ استانداردهای این فصل را رعایت میکند، گابریل وابسته به فناوری اختصاصی یا یک فروشندهٔ خاص نیست.
- هنگام اولین استفاده، دستگاه با مولد عدد تصادفی سختافزاری داخلی خود mnemonic و بذر را ساخت و واژهها را شمارهدار و یکییکی روی صفحه نشان داد.
- گابریل واژهها را روی یک برگهٔ پشتیبان شمارهدار نوشت (جدول ۵-۱: ۱ army، ۲ van، ۳ defense، ۴ carry، ۵ jealous، ۶ true، ۷ garbage، ۸ claim، ۹ echo، ۱۰ media، ۱۱ make، ۱۲ crunch). ترتیب واژهها مهم است، برای همین برگههای پشتیبان جای شمارهدار دارند.
- این پشتیبان در صورت گمشدن یا آسیب دیدن Trezor، در یک Trezor جدید یا هر کیف پول سازگار دیگر قابل استفاده است.
- نمونهٔ ۱۲ کلمهای برای سادگی آمده؛ بیشتر کیف پولهای سختافزاری mnemonic امنتر ۲۴ کلمهای میسازند و شیوهٔ کار با هر طولی یکی است.
در نسخهٔ اول فروشگاهش، گابریل فقط یک آدرس بیتکوین (ساختهشده روی Trezor) برای همهٔ مشتریان و همهٔ سفارشها استفاده میکند؛ رویکردی که معایبی دارد و با HD قابل بهبود است (ادامهٔ داستان در بخش xpub).
جزئیات فناوری کیف پول
کلمات یادآور (BIP-39)
mnemonic دنبالهٔ واژههایی است که یک عدد تصادفی (بذر) را کدگذاری میکند. کیف پول هنگام ساخت ۱۲ تا ۲۴ واژه نشان میدهد که همان پشتیبان کیف پول است و در همان کیف پول یا هر برنامهٔ سازگار میتواند همهٔ کلیدها را بازسازی کند؛ خواندن و رونویسی صحیح آنها از دنبالهٔ اعداد آسانتر است.
تفاوت با brainwallet: در brainwallet واژهها را کاربر انتخاب میکند، ولی در mnemonic واژهها را کیف پول بهطور تصادفی میسازد. چون انسان منبع تصادفی بسیار ضعیفی است، mnemonic بهمراتب امنتر است.
پیشینه: BIP-39 را شرکت سازندهٔ Trezor پیشنهاد داد. استاندارد قدیمیتری با فهرست واژهٔ متفاوت در کیف پول Electrum هست که با آن ناسازگار است؛ با این حال BIP-39 حمایت گستردهٔ صنعتی و دهها پیادهسازی دارد و عملاً استاندارد است.
تولید کلمات (مراحل ۱ تا ۶)
- دنبالهٔ تصادفی (آنتروپی) با طول ۱۲۸ تا ۲۵۶ بیت بساز.
- چکسام را از اولین (طول آنتروپی ÷ ۳۲) بیتِ هش SHA256 آن بگیر.
- چکسام را به انتهای دنباله بچسبان.
- دنباله را به قطعههای ۱۱ بیتی تقسیم کن.
- هر مقدار ۱۱ بیتی را با فرهنگ لغت از پیش تعریفشدهٔ ۲۰۴۸ واژهای به یک واژه نگاشت کن.
- دنبالهٔ واژهها همان mnemonic است.
رابطهٔ اندازهٔ آنتروپی و طول mnemonic (جدول ۵-۲):
| آنتروپی (بیت) | چکسام (بیت) | آنتروپی + چکسام | تعداد واژه |
|---|---|---|---|
| ۱۲۸ | ۴ | ۱۳۲ | ۱۲ |
| ۱۶۰ | ۵ | ۱۶۵ | ۱۵ |
| ۱۹۲ | ۶ | ۱۹۸ | ۱۸ |
| ۲۲۴ | ۷ | ۲۳۱ | ۲۱ |
| ۲۵۶ | ۸ | ۲۶۴ | ۲۴ |
از mnemonic تا بذر (مراحل ۷ تا ۹)
واژهها آنتروپی ۱۲۸ تا ۲۵۶ بیتی را نمایندگی میکنند و با تابع کشش کلید PBKDF2 به بذر بلندتر ۵۱۲ بیتی تبدیل میشوند. این تابع دو ورودی دارد: mnemonic و یک نمک (salt). نمک اولاً ساخت جدول جستجو برای حملهٔ brute-force را دشوار میکند و ثانیاً در BIP-39 امکان افزودن یک عبارت عبور اختیاری را فراهم میکند که عامل امنیتی اضافه است.
- ورودی اول PBKDF2 همان mnemonic مرحلهٔ ۶ است.
- ورودی دوم نمک است: رشتهٔ ثابت
"mnemonic"بهعلاوهٔ عبارت عبور اختیاری کاربر. - PBKDF2 با ۲۰۴۸ دور هش HMAC-SHA512 خروجی ۵۱۲ بیتی میدهد؛ همان بذر.
این کشش (۲۰۴۸ دور) دفاع مؤثری در برابر brute-force روی mnemonic یا عبارت عبور است و آزمودن حتی چند هزار ترکیب را از نظر محاسباتی پرهزینه میکند، در حالی که فضای بذرهای ممکن حدود ۲^۵۱۲ است.
کتاب سه نمونه آورده است (جداول ۵-۳ تا ۵-۵):
- آنتروپی ۱۲۸ بیتی
0c1e24e5…1a1a← ۱۲ واژه (همان «army van defense…») بدون عبارت عبور ← بذری که با5b56c417…شروع میشود. - همان mnemonic با عبارت عبور
SuperDuperSecret← بذری کاملاً متفاوت (شروع با3b5df16d…). - آنتروپی ۲۵۶ بیتی ← ۲۴ واژه (از «cake apple borrow…» تا «…dilemma oblige») بدون عبارت عبور ← بذر با شروع
3269bce2….
عبارت عبور اختیاری در BIP-39
بدون عبارت عبور، نمک فقط رشتهٔ "mnemonic" است و از هر mnemonic یک بذر مشخص حاصل میشود. با عبارت عبور، از همان mnemonic بذر دیگری به دست میآید. در واقع «عبارت عبور اشتباه» وجود ندارد: هر عبارت معتبر است و کیف پولی متفاوت (که تا قبل از استفاده خالی است) میدهد. چون تعداد کیف پولهای ممکن (۲^۵۱۲) عظیم است، حدسزدن تصادفی یا brute-force عملاً ناممکن است. دو کاربرد:
- عامل دوم (چیزی که حفظ میکنید): mnemonic تنهایی بیفایده میشود و پشتیبان کاغذی در برابر سرقت محافظت میشود.
- انکارپذیری معقول / کیف پول تحت تهدید (duress wallet): با یک عبارت عبور خاص به کیف پولی با مبلغ ناچیز میرسید که مهاجم را از کیف پول اصلی منحرف میکند.
خطرها: اگر مالک بمیرد یا ناتوان شود و کسی عبارت عبور را نداند، بذر بیفایده است و وجوه برای همیشه از دست میرود؛ و اگر عبارت عبور کنار بذر نگهداری شود، فلسفهٔ عامل دوم از بین میرود. پس استفاده از آن نیازمند برنامهٔ دقیق پشتیبانگیری و بازیابی است که امکان بازیابی ارزهای رمزنگاریشده توسط خانواده را هم لحاظ کند.
کار با mnemonic
BIP-39 در کتابخانههای بسیاری پیادهسازی شده است:
python-mnemonic: پیادهسازی مرجع (تیم SatoshiLabs که BIP-39 را پیشنهاد داد)، پایتونbitcoinjs/bip39: بخشی از چارچوب bitcoinJS، جاوااسکریپتlibbitcoin/mnemonic: بخشی از Libbitcoin، سیپلاسپلاس
همچنین یک مولد BIP-39 بهصورت صفحهٔ وب مستقل هست که برای آزمایش بسیار مفید است و mnemonic، بذر و کلید خصوصی توسعهیافته تولید میکند؛ هم آفلاین در مرورگر و هم آنلاین قابل استفاده است.
ساخت کیف پول HD از بذر
کیف پول HD از یک بذر ریشه (عدد تصادفی ۱۲۸، ۲۵۶ یا ۵۱۲ بیتی، که معمولاً از mnemonic بهدست میآید) ساخته میشود. همهٔ کلیدها بهطور قطعی از این بذر میآیند، پس فقط با انتقال mnemonic میتوان کیف پولی با هزاران یا میلیونها کلید را پشتیبانگیری، بازیابی، export و import کرد.
ساخت کلیدهای اصلی: بذر ریشه به HMAC-SHA512 داده میشود و هش حاصل کلید خصوصی اصلی (m) و chain code اصلی (c) را میسازد. از m با ضرب منحنی بیضوی m * G کلید عمومی اصلی (M) بهدست میآید. chain code برای وارد کردن آنتروپی اضافی در تابع مشتقگیری فرزندان از والدین به کار میرود.
مشتقگیری کلید فرزند خصوصی
HD از تابع مشتقگیری کلید فرزند (CKD) برای ساخت فرزندان از والد استفاده میکند. این تابع بر اساس یک هش یکطرفه است و سه ورودی را ترکیب میکند:
- کلید والد (خصوصی یا عمومی)
- یک chain code ۲۵۶ بیتی
- یک شمارهٔ ایندکس ۳۲ بیتی
chain code دادهای تصادفی-قطعی وارد فرایند میکند، بهطوری که دانستن ایندکس و یک کلید فرزند برای استخراج بقیهٔ فرزندان کافی نیست. chain code اولیه از بذر ساخته میشود و chain codeهای فرزندان از chain code والد.
نحوهٔ کار: کلید عمومی والد، chain code و ایندکس با HMAC-SHA512 هش میشوند و خروجی ۵۱۲ بیتی به دو نیمهٔ ۲۵۶ بیتی تقسیم میشود. نیمهٔ راست chain code فرزند میشود؛ نیمهٔ چپ (همراه ایندکس) به کلید خصوصی والد افزوده میشود تا کلید خصوصی فرزند به دست آید. با تغییر ایندکس (۰، ۱، ۲ و…) فرزندان دیگر ساخته میشوند. هر والد میتواند ۲^۳۱ (۲٬۱۴۷٬۴۸۳٬۶۴۸) فرزند عادی داشته باشد، چون نیمهٔ دیگر ایندکسها برای نوع خاصی از مشتقگیری (سختشده) کنار گذاشته شده است. هر فرزند میتواند خود والد شود و تا نسلهای نامحدود ادامه یابد.
استفاده از کلیدهای فرزند:
- کلید خصوصی فرزند از کلیدهای تصادفی قابل تشخیص نیست.
- چون تابع یکطرفه است، از فرزند نمیتوان به والد یا خواهر/برادرها (ایندکس n−1 یا n+1) رسید. فقط والد بههمراه chain code میتواند همهٔ فرزندان را بسازد.
- بدون chain code فرزند، نمیتوان نوه ساخت؛ برای شروع یک شاخهٔ جدید به هر دو، کلید خصوصی فرزند و chain code فرزند، نیاز است.
- کلید فرزند بهتنهایی برای ساخت کلید عمومی و آدرس بیتکوین و امضای تراکنش خرجکردن وجوه همان آدرس کافی است.
- کلید، کلید عمومی و آدرس مشتقشده از بیرون کیف پول HD با کلیدهای تصادفی تفاوت قابل مشاهده ندارند و عضویت در یک دنباله فقط داخل کیف پول مشخص است.
کلیدهای توسعهیافته (Extended Keys)
ترکیب کلید و chain code را کلید توسعهیافته میگویند (میتوان «کلید قابلتوسعه» هم خواند، چون فرزند میسازد). بهصورت الحاق کلید ۲۵۶ بیتی و chain code ۲۵۶ بیتی (۵۱۲ بیت) ذخیره میشود. دو نوع دارد:
- کلید خصوصی توسعهیافته: کلید خصوصی + chain code؛ فرزندان خصوصی (و از آنها عمومی) میسازد.
- کلید عمومی توسعهیافته: کلید عمومی + chain code؛ فقط فرزندان عمومی میسازد.
هر کلید توسعهیافته ریشهٔ یک شاخه است؛ اشتراکگذاری آن دسترسی به کل شاخه میدهد.
برای تبادل بین کیف پولهای سازگار با BIP-32، کلیدهای توسعهیافته با Base58Check و یک شمارهٔ نسخهٔ ویژه کدگذاری میشوند تا پیشوند آنها xprv (خصوصی) و xpub (عمومی) باشد. چون ۵۱۲ یا ۵۱۳ بیتاند، از رشتههای Base58Check قبلی بسیار بلندترند. مثال کتاب: یک xprv9tyUQV64… و xpub67xpozcx… متناظر.
مشتقگیری کلید فرزند عمومی
ویژگی کلیدی HD: ساخت کلید عمومی فرزند از کلید عمومی والد، بدون کلید خصوصی. پس دو راه برای کلید عمومی فرزند داریم: از کلید خصوصی فرزند، یا مستقیم از کلید عمومی والد. یک xpub میتواند همهٔ کلیدهای عمومی (و فقط عمومی) آن شاخه را مشتق کند. کاربردها:
- استقرار فقطعمومی امن: سرور یا برنامه فقط xpub دارد و میتواند بینهایت کلید عمومی و آدرس بسازد ولی نمیتواند وجوه را خرج کند؛ کلید خصوصی توسعهیافته روی سرور امنتر دیگر، برای امضا نگهداری میشود.
- فروشگاه آنلاین: xpub روی وبسرور نصب میشود و برای هر تراکنش (مثلاً هر سبد خرید) آدرس جدید میسازد، بدون اینکه کلید خصوصی قابل سرقتی در آنجا باشد. بدون HD باید هزاران آدرس را روی سرور امن جداگانه ساخت و از پیش روی سرور فروشگاه بارگذاری کرد، که دستوپاگیر است و نگهداری دائمی میخواهد تا آدرسها تمام نشوند.
- ذخیرهسازی سرد و کیف پول سختافزاری: کلید خصوصی توسعهیافته روی کیف پول کاغذی یا دستگاه (مثل Trezor) آفلاین میماند و xpub آنلاین است. کاربر هر زمان بخواهد آدرس دریافت میسازد و برای خرجکردن، از کلاینت امضای آفلاین یا دستگاه سختافزاری استفاده میکند.
استفاده از xpub در وبفروشگاه (ادامهٔ داستان گابریل)
فروشگاه گابریل ابتدا یک سرگرمی روی صفحهٔ سادهی WordPress با یک فرم سفارش و یک آدرس بیتکوین بود (اولین آدرس ساختهشده توسط Trezor). مشتری فرم را پر میکرد، به آدرس پرداخت میکرد و ایمیل سفارش برای گابریل میآمد. با رونق فروشگاه، چون همهٔ سفارشها به یک آدرس پرداخت میشد، تطبیق سفارشها با تراکنشها (بهویژه سفارشهای هممبلغ و نزدیک به هم) دشوار شد.
راهحل HD: گابریل xpub را روی وبسایتش بارگذاری میکند تا برای هر سفارش آدرس یکتا بسازد. وجوه را فقط با Trezor میشود خرج کرد و xpub وبسایت صرفاً آدرس میسازد و دریافت میکند؛ یعنی سایت کلید خصوصی ندارد و سطح بالای امنیت لازم ندارد. برای export، گابریل از نرمافزار تحت وب بههمراه Trezor متصل استفاده میکند. کیف پولهای سختافزاری هرگز کلید خصوصی را export نمیکنند؛ کلید خصوصی روی دستگاه میماند. سپس xpub را در افزونهٔ Mycelium Gear (افزونهٔ متنباز وبفروشگاه برای پلتفرمهای مختلف) قرار میدهد که برای هر خرید آدرس منحصربهفرد میسازد.
مشتقگیری سختشده (Hardened)
xpub مفید است ولی ریسکی دارد: xpub دسترسی به کلیدهای خصوصی فرزند نمیدهد، اما چون chain code را در خود دارد، اگر یک کلید خصوصی فرزند فاش شود، همراه chain code والد همهٔ کلیدهای خصوصی فرزندان دیگر را آشکار میکند، و بدتر، قابل استفاده برای استنتاج کلید خصوصی والد است.
راهحل مشتقگیری سختشده است که ارتباط کلید عمومی والد و chain code فرزند را «میشکند». این تابع تقریباً مثل مشتقگیری عادی است، با این تفاوت که بهجای کلید عمومی والد، کلید خصوصی والد وارد هش میشود. حاصل یک «دیوار آتش» است: chain code فرزند سختشده نمیتواند برای به خطر انداختن کلید خصوصی والد یا خواهر/برادر به کار رود. کلید و chain code خروجی کاملاً با مشتقگیری عادی متفاوت است. بنابراین سختشدهسازی یک «شکاف» در درخت بالای سطحی ایجاد میکند که xpub در آن استفاده میشود. اگر میخواهید از xpub استفاده کنید و از نشت chain code ایمن باشید، آن را از والد سختشده بسازید، نه والد عادی. بهترین شیوه: فرزندان سطح ۱ از کلیدهای اصلی همیشه با مشتقگیری سختشده ساخته میشوند تا کلیدهای اصلی آسیب نبینند.
شمارهٔ ایندکس برای مشتقگیری عادی و سختشده
ایندکس عدد ۳۲ بیتی است و دو بازه دارد:
| بازه | محدوده (هگز) | نوع |
|---|---|---|
| ۰ تا ۲^۳۱−۱ | 0x0 تا 0x7FFFFFFF |
فقط عادی |
| ۲^۳۱ تا ۲^۳۲−۱ | 0x80000000 تا 0xFFFFFFFF |
فقط سختشده |
برای خوانایی، ایندکسهای سختشده از صفر و با علامت پریم (‘) نمایش داده میشوند: اولین فرزند عادی 0، اولین فرزند سختشده (ایندکس 0x80000000) 0'، دومی (0x80000001) 1' و… یعنی i' برابر ۲^۳۱+i است.
مسیر کلید (path)
کلیدهای HD با قرارداد «مسیر» نامگذاری میشوند و هر سطح درخت با / جدا میشود. کلید خصوصی مشتق از کلید خصوصی اصلی با m و کلید عمومی مشتق از کلید عمومی اصلی با M شروع میشود. «نسب» کلید از راست به چپ تا رسیدن به کلید اصلی خوانده میشود: m/x/y/z یعنی z-امین فرزند m/x/y، که y-امین فرزند m/x و آن x-امین فرزند m است. نمونهها (جدول ۵-۶):
| مسیر | کلید توصیفشده |
|---|---|
m/0 |
اولین فرزند کلید خصوصی اصلی |
m/0/0 |
اولین نوهٔ اولین فرزند |
m/0'/0 |
اولین نوهٔ عادی از اولین فرزند سختشده |
m/1/0 |
اولین نوه از فرزند دوم |
M/23/17/0/0 |
کلید عمومی اولین نبیرهٔ دوم (چهارمین سطح) از زنجیرهای که از ۲۴-امین فرزند و ۱۸-امین نوه میگذرد |
پیمایش درخت: BIP-43 و BIP-44
هر والد میتواند ۴ میلیارد فرزند داشته باشد (۲ میلیارد عادی و ۲ میلیارد سختشده) و هر کدام باز همینقدر؛ پیمایش و بهویژه انتقال کیف پول بین پیادهسازیها دشوار میشود، چون سازماندهی داخلی بیپایان است. دو BIP ساختار پیشنهادی ارائه میدهند:
- BIP-43: اولین ایندکس سختشده را بهعنوان شناسهٔ «هدف» (purpose) ساختار درخت تعریف میکند. کیف پول فقط از یک شاخهٔ سطح ۱ استفاده میکند که ایندکس آن ساختار و فضای نام بقیهٔ درخت را مشخص میکند (مثلاً
m/i'/). - BIP-44: ساختار چندحسابی را با purpose شمارهٔ
44'تعریف میکند. همهٔ کیف پولهای پیرو آن فقط از شاخهٔm/44'/استفاده میکنند.
ساختار پنجسطحی BIP-44:
m / purpose' / coin_type' / account' / change / address_index
- purpose: همیشه
44'. - coin_type: نوع ارز، برای کیف پولهای چندارزی که هر ارز زیردرخت خود را دارد. سه ارز تعریفشده: بیتکوین
m/44'/0'، تستنت بیتکوینm/44'/1'، لایتکوینm/44'/2'. - account: تقسیم کیف پول به زیرحسابهای منطقی برای حسابداری یا سازماندهی؛ مثلاً
m/44'/0'/0'وm/44'/0'/1'دو حساب بیتکوین، هرکدام ریشهٔ زیردرخت خود. - change: دو زیردرخت: یکی برای آدرسهای دریافت و یکی برای آدرسهای باقیمانده. برخلاف سطوح قبل که سختشدهاند، این سطح مشتقگیری عادی دارد تا بتوان xpub این سطح را در محیط ناامن export کرد.
- address_index: آدرسهای قابل استفاده، فرزندان سطح چهارم (سطح پنجم درخت).
نمونهها (جدول ۵-۷):
| مسیر | توضیح |
|---|---|
M/44'/0'/0'/0/2 |
سومین کلید عمومی دریافت برای حساب اصلی بیتکوین |
M/44'/0'/3'/1/14 |
پانزدهمین کلید عمومی آدرس باقیمانده برای چهارمین حساب بیتکوین |
m/44'/2'/0'/0/1 |
دومین کلید خصوصی حساب اصلی لایتکوین برای امضای تراکنشها |
جمعبندی
- کیف پول بیتکوین کلید نگه میدارد، نه سکه؛ سکهها بهصورت UTXO در بلاکچین هستند و کلیدها اجازهٔ خرجکردن میدهند.
- کیف پول غیرقطعی (JBOK) برای مدیریت و پشتیبانگیری دردسرساز است و با حریم خصوصی (عدم استفادهٔ مجدد از آدرس) جور نیست؛ استفاده از آن فقط برای آزمایشهاست. کیف پول قطعی همهٔ کلیدها را از یک بذر میسازد و یک پشتیبان کافی است.
- استاندارد عملی صنعت چهار BIP همپیوند است: BIP-39 (mnemonic ۱۲ تا ۲۴ واژه از فهرست ۲۰۴۸ کلمهای، چکسام SHA256، بذر ۵۱۲ بیتی با PBKDF2 و ۲۰۴۸ دور HMAC-SHA512)، BIP-32 (درخت HD با chain code و ایندکس ۳۲ بیتی)، BIP-43 (purpose) و BIP-44 (
m/44'/coin'/account'/change/index). - عبارت عبور اختیاری BIP-39 عامل دوم و امکان کیف پول تحت تهدید میدهد، اما اگر فراموش یا ناشناخته بماند، وجوه برای همیشه از دست میرود؛ پس به برنامهٔ بازیابی نیاز دارد.
- کلیدهای توسعهیافته (
xprv/xpub، کلید + chain code) امکان ساخت شاخهای از کلیدها را میدهند؛ xpub روی سرور فروشگاه یا کیف پول سختافزاری آدرسهای دریافت یکتا میسازد بدون در معرض گذاشتن کلید خصوصی، و برای هر سفارش آدرس جدید میدهد (مثل فروشگاه گابریل با Trezor و Mycelium Gear). - مشتقگیری سختشده (ایندکس ≥ ۲^۳۱، نماد پریم) خطر نشت یک کلید فرزند + chain code را قطع میکند؛ فرزندان سطح ۱ کلید اصلی و سطوح purpose/coin/account سختشدهاند، اما سطح change و address_index عادیاند تا xpub سطح حساب قابل export باشد.
- کیف پول جدید را باید HD با بذر mnemonic و منطبق بر BIP-32/39/43/44 ساخت تا با Trezor، Ledger، Keepkey، Copay، Mycelium و دیگران همکاریپذیر باشد.
فصل ۶ — تراکنشها (Transactions)
مقدمه
تراکنش (Transaction) مهمترین بخش سیستم بیتکوین است. بقیهٔ اجزا (شبکه، بلاکها، ماینینگ، اجماع) برای این طراحی شدهاند که تراکنشها ساخته شوند، در شبکه پخش شوند، اعتبارسنجی شوند و در نهایت به دفتر کل جهانی یعنی بلاکچین اضافه شوند. تراکنش ساختار دادهای است که انتقال ارزش بین شرکتکنندگان را رمز میکند و هر تراکنش یک رکورد عمومی در این دفتر حسابداری دوطرفه است. در این فصل واژهٔ «کیف پول» به نرمافزاری اشاره دارد که تراکنش میسازد، نه صرفاً پایگاه دادهٔ کلیدها.
تراکنشها در جزئیات
پشت صحنهٔ تراکنش
در فصل ۲ تراکنش پرداخت آلیس برای قهوه در کافهٔ باب را با یک block explorer دیدیم؛ نمایی ساده که یک «آدرس فرستنده» و یک «آدرس گیرنده» نشان میدهد. واقعیت این است که بخش زیادی از آن اطلاعات را خود explorer میسازد و در تراکنش وجود ندارد. با دستورهای getrawtransaction و decoderawtransaction در Bitcoin Core میتوان تراکنش خام آلیس را دید:
version(برابر ۱) وlocktime(برابر ۰)؛- آرایهٔ
vinبا یک ورودی:txidتراکنش قبلی (7957a35f…6f18)،voutبرابر ۰، یکscriptSig(شامل امضا با پسوند[ALL]و کلید عمومی) وsequenceبرابر ۴۲۹۴۹۶۷۲۹۵ (یعنی0xFFFFFFFF)؛ - آرایهٔ
voutبا دو خروجی: ۰٫۰۱۵ BTC و ۰٫۰۸۴۵ BTC، هرکدام با اسکریپت قفلOP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG.
نکتهٔ مهم چیزهایی است که وجود ندارند: آدرس آلیس، آدرس باب، و «۰٫۱ بیتکوینی که آلیس فرستاد». در بیتکوین سکه، فرستنده، گیرنده، موجودی، حساب و آدرس (بهعنوان فیلد) وجود ندارد؛ همهٔ اینها مفاهیمیاند که لایههای بالاتر برای راحتی کاربر میسازند.
خروجی و ورودی تراکنش، و مفهوم UTXO
سنگبنای تراکنش خروجی تراکنش (transaction output) است: تکههای تقسیمناپذیر ارز بیتکوین که روی بلاکچین ثبت شده و کل شبکه آن را معتبر میشناسد. گرههای کامل همهٔ خروجیهای خرجنشده را نگه میدارند؛ اینها UTXO (Unspent Transaction Output) نام دارند و مجموعهٔ آنها UTXO set است (در زمان کتاب در حد میلیونها خروجی). هر تراکنش یک انتقال وضعیت (state transition) در این مجموعه است: خروجیهایی مصرف و خروجیهای تازهای ساخته میشود.
- وقتی میگوییم کیف پولی بیتکوین «دریافت کرده»، یعنی UTXOای شناسایی کرده که با یکی از کلیدهای تحت کنترلش قابل خرج است. موجودی مجموع همهٔ UTXOهای قابلخرج است که ممکن است بین صدها تراکنش و بلاک پراکنده باشد؛ این مفهوم را خود کیف پول با اسکن بلاکچین (یا نگهداشتن یک پایگاه دادهٔ محلی) محاسبه میکند.
- مقدار هر خروجی یک عدد صحیح بر حسب ساتوشی است (یک صدمیلیونیوم بیتکوین، هشت رقم اعشار). هر خروجی پس از ایجاد تقسیمناپذیر است و فقط بهطور کامل خرج میشود.
- اگر UTXO بزرگتر از مبلغ مورد نیاز باشد، باید باقیمانده (change) تولید شود. مثال: برای پرداخت ۱ BTC با یک UTXO بیستبیتکوینی، تراکنش دو خروجی میسازد: یک بیتکوین برای گیرنده و ۱۹ بیتکوین بازگشت به کیف پول خودتان. تشبیه کتاب: خریدار نوشیدنی ۱٫۵۰ دلاری که اسکناس ۵ دلاری میدهد و ۳٫۵۰ دلار بازمیگیرد؛ اسکناس را نمیشود نصف کرد.
- کیف پول بهطور خودکار UTXOها را انتخاب میکند (ترکیب چند خروجی کوچک، پیدا کردن مبلغ دقیق، یا استفاده از یک خروجی بزرگتر و ساخت باقیمانده). این پیچیدگی فقط برای کسی که تراکنش خام را برنامهنویسی میکند مهم است.
- زنجیرهٔ «خروجی ← ورودی» استثنا دارد: تراکنش coinbase، اولین تراکنش هر بلاک که ماینر برنده میسازد و بیتکوین تازه (پاداش ماینینگ) را ایجاد میکند. این تراکنش UTXO مصرف نمیکند و ورودی ویژهای به نام coinbase دارد؛ به این ترتیب عرضهٔ پول ساخته میشود (فصل ۱۰). پس بهبیان دقیق، خروجیها مقدماند چون coinbase بدون ورودی خروجی میسازد.
خروجیهای تراکنش
هر تراکنش خروجیهایی میسازد که روی دفتر کل ثبت میشوند و (بهجز یک استثنا یعنی خروجی ثبت داده با OP_RETURN) UTXO قابلخرجاند. هر خروجی دو بخش دارد:
- مقدار بر حسب ساتوشی؛
- یک معمای رمزنگاریشده که شرط خرجکردن را تعیین میکند؛ با نامهای اسکریپت قفل (locking script)، witness script یا
scriptPubKey.
Bitcoin Core مقدار را برای خوانایی به بیتکوین نشان میدهد، اما در خود تراکنش عدد صحیح ساتوشی است. تراکنش آلیس دو خروجی دارد: ۰٫۰۱۵ برای کافهٔ باب و ۰٫۰۸۴۵ باقیمانده برای خود آلیس.
سریالسازی خروجیها
سریالسازی (serialization) یعنی تبدیل ساختار داخلی به جریان بایتی برای ارسال در شبکه یا ذخیره. بازگشت آن deserialization یا parsing نامیده میشود. کتابخانهها تراکنش را داخل حافظه بهصورت ساختار شیءگرا نگه میدارند، نه بایت خام. قالب هر خروجی:
| اندازه | فیلد | توضیح |
|---|---|---|
| ۸ بایت (little-endian) | Amount | مقدار به ساتوشی |
| ۱ تا ۹ بایت (VarInt) | Locking-Script Size | طول اسکریپت قفل به بایت |
| متغیر | Locking-Script | اسکریپت شرط خرج |
راهنمای رمزگشایی دستی تراکنش آلیس: ۰٫۰۱۵ BTC برابر ۱٬۵۰۰٬۰۰۰ ساتوشی یعنی 16 e3 60 در مبنای ۱۶ است که بهصورت little-endian به شکل 60 e3 16 … در جریان بایتی ظاهر میشود؛ طول اسکریپت قفل ۲۵ بایت یعنی 19 در هگز است.
ورودیهای تراکنش
ورودی با ارجاع، مشخص میکند کدام UTXO مصرف میشود و با اسکریپت باز (unlocking script) مالکیت را اثبات میکند. کیف پول بهاندازهٔ نیاز UTXO برمیگزیند و برای هر کدام یک ورودی میسازد. هر ورودی چهار عنصر دارد:
- شناسهٔ تراکنشی که UTXO در آن است (txid)؛
- اندیس خروجی (
vout) در آن تراکنش، با شروع از صفر؛ scriptSigکه شرایط قفل را برآورده میکند (اغلب امضای دیجیتال و کلید عمومی، اما هر اسکریپت باز لزوماً امضا ندارد)؛- شمارهٔ ترتیب (sequence number).
در تراکنش آلیس ورودی به txid 7957a35f… و اندیس ۰ اشاره میکند. نکتهٔ کلیدی: ورودی مقدار و اسکریپت قفل UTXO را نمیگوید. برای دانستن آنها باید تراکنش مرجع را بازیابی کرد (در مثال، ۰٫۱ BTC با قفل P2PKH). به همین دلیل:
- تراکنش بهتنهایی «بیبافت» است؛ برای اعتبارسنجی، شمارش کارمزد یا بررسی اسکریپت باز، نرمافزار ابتدا باید UTXOهای ارجاعشده را از بلاکچین بگیرد. حتی محاسبهٔ سادهی کارمزد به دادههای چند تراکنش نیاز دارد؛
- همهٔ گرههای اعتبارسنج نیز همین کار را برای هر ورودی میکنند. تقریباً هر کتابخانهٔ بیتکوین تابعی برای بازیابی تراکنشها و UTXOهای قبلی دارد.
سریالسازی ورودیها
| اندازه | فیلد | توضیح |
|---|---|---|
| ۳۲ بایت | Transaction Hash | اشارهگر به تراکنش حاوی UTXO |
| ۴ بایت | Output Index | اندیس UTXO، اولی ۰ |
| ۱ تا ۹ بایت (VarInt) | Unlocking-Script Size | طول اسکریپت باز |
| متغیر | Unlocking-Script | اسکریپتی که شرط قفل را برآورده میکند |
| ۴ بایت | Sequence Number | برای locktime، یا غیرفعال با 0xFFFFFFFF |
نکات رمزگشایی: txid در جریان بایتی با ترتیب معکوس ذخیره میشود (با 18 شروع و با 79 تمام میشود)؛ اندیس خروجی چهار بایت صفر است؛ طول scriptSig برابر ۱۳۹ بایت یعنی 8b است؛ و sequence برابر ffffffff است.
کارمزد تراکنش
بیشتر تراکنشها کارمزد دارند که ماینرها را برای تأمین امنیت شبکه جبران میکند و همزمان سازوکار امنیتی است، چون سیلآسا کردن شبکه با تراکنش را از نظر اقتصادی غیرممکن میسازد. کارمزد به ماینری میرسد که بلاک حاوی تراکنش را استخراج میکند. نکات اصلی:
- کارمزد بر اساس اندازهٔ تراکنش (کیلوبایت) محاسبه میشود، نه مبلغ بیتکوین منتقلشده؛ و بر اساس نیروهای بازار شکل میگیرد. ماینرها با معیارهای مختلف (از جمله کارمزد) اولویتبندی میکنند. تراکنش با کارمزد کافی احتمالاً در بلاک بعدی میآید؛ بدون کارمزد ممکن است به تعویق بیفتد یا هرگز استخراج نشود.
- تاریخچه: ابتدا کارمزدها ثابت و یکسان بودند؛ بهتدریج بازارمحور شدند. از دستکم ابتدای ۲۰۱۶ محدودیت ظرفیت رقابت ایجاد کرد و تراکنشهای رایگان عملاً از بین رفتند؛ تراکنش با کارمزد صفر یا بسیار کم معمولاً استخراج نمیشود و گاهی حتی پخش هم نمیشود.
- در Bitcoin Core سیاست رله با گزینهٔ
minrelaytxfeeتعیین میشود. پیشفرض ۰٫۰۰۰۰۱ بیتکوین به ازای هر کیلوبایت است؛ تراکنشهای زیر آن «رایگان» تلقی میشوند و فقط در صورت جا داشتن mempool رله میشوند. - هر سرویسی که تراکنش میسازد باید کارمزد پویا (dynamic fee) داشته باشد؛ با سرویس شخص ثالث یا الگوریتم تخمین داخلی (از میانگین/میانهٔ کارمزد بلاک اخیر تا تحلیل آماری). سرویسها معمولاً سه اولویت بالا، متوسط و پایین میدهند. کارمزد ایستا دیگر کارآمد نیست و تراکنشها «گیر» میکنند و کاربر میترسد پولش را از دست داده است.
- مثال کتاب: سرویس bitcoinfees.21.co نمودار کارمزد بر حسب ساتوشی بر بایت را نشان میداد؛ توصیهٔ اولویت بالا ۸۰ ساتوشی/بایت بود. با اندازهٔ میانهٔ تراکنش ۲۲۶ بایت، کارمزد ۱۸٬۰۸۰ ساتوشی (۰٫۰۰۰۱۸۰۸۰ BTC) میشود. API آن (
/api/v1/fees/recommended) سه مقدارfastestFee،halfHourFee(حدود سه بلاک) وhourFee(حدود شش بلاک) برمیگرداند.
افزودن کارمزد به تراکنش
ساختار تراکنش فیلد کارمزد ندارد؛ کارمزد ضمنی است:
کارمزد = مجموع ورودیها − مجموع خروجیها
هر مقدار مازاد به ماینر میرسد. پس در تراکنش دستی باید همهٔ ورودیها را حساب کرد و در صورت لزوم خروجی باقیمانده ساخت، وگرنه باقیمانده بهعنوان کارمزد از دست میرود («بقیهاش مال شما!»). مثال ۲۰ BTC مصرفی برای پرداخت ۱ BTC بدون خروجی باقیمانده، ۱۹ BTC کارمزد میشود.
- سناریوی آلیس: او میخواهد ۰٫۰۱۵ بپردازد و ۰٫۰۰۱ کارمزد بدهد (جمعاً ۰٫۰۱۶). کیف پول یک UTXO ۰٫۲ بیتکوینی مصرف میکند، ۰٫۰۱۵ به کافه و ۰٫۱۸۴ به باقیمانده میدهد و ۰٫۰۰۱ ناتخصیصیافته کارمزد ضمنی میشود.
- سناریوی Eugenia (مدیر خیریه در فیلیپین): ۵۰ BTC از هزاران کمکمالی کوچک جمع کرده و کیف پولش پر از UTXOهای ریز است. پرداخت یکجا به ناشر کتاب بیش از صد ورودی و یک خروجی دارد و اندازهاش از یک کیلوبایت فراتر میرود؛ پس کارمزد بسیار بالاتر از تراکنش میانه است. دلیل، پیچیدگی و حجم است نه مبلغ.
اسکریپتهای تراکنش و زبان Script
زبان تراکنش بیتکوین، Script، زبانی پشتهمحور شبیه Forth با نمادگذاری لهستانی معکوس (RPN) است. هم اسکریپت قفل خروجی و هم اسکریپت باز ورودی با آن نوشته میشوند و هنگام اعتبارسنجی، اسکریپت باز هر ورودی همراه اسکریپت قفل متناظرش اجرا میشود تا ببینیم شرط خرج برآورده شده است یا نه. زبان عمداً ساده و محدود طراحی شده و حتی روی سختافزار ساده کار میکند؛ این محدودیت یک ویژگی امنیتی است.
امروزه بیشتر تراکنشها «پرداخت به آدرس باب» هستند و بر اسکریپت P2PKH تکیه دارند، اما اسکریپت قفل میتواند شرطهای بسیار متنوع بیان کند؛ از اینجا «پول برنامهپذیر» (programmable money) میآید.
ناتمام بودن تورینگ
Script حلقه و کنترل جریان پیچیده ندارد (فقط شرطی). بنابراین تورینگکامل نیست: پیچیدگی و زمان اجرای آن قابلپیشبینی است و نمیتوان حلقهٔ بینهایت یا «بمب منطقی» برای حملهٔ منع سرویس به شبکه در تراکنش جا داد؛ چون هر تراکنش را همهٔ گرههای کامل اعتبارسنجی میکنند.
راستیآزمایی بدون حالت (Stateless)
Script بدون حالت است: نه وضعیتی پیش از اجرا دارد و نه پس از اجرا ذخیره میکند. همهٔ اطلاعات لازم در خود اسکریپت است، پس روی هر سیستمی دقیقاً یک نتیجه میدهد. اگر گره شما تراکنشی را معتبر بداند، همهٔ گرهها هم میدانند.
ساختار قفل + باز
- اسکریپت قفل: شرطی که روی خروجی گذاشته میشود. نام تاریخی
scriptPubKeyاست چون معمولاً کلید عمومی یا آدرس (هش کلید عمومی) داشت؛ در کتاب «اسکریپت قفل» نامیده میشود چون دامنهٔ کاربردش وسیعتر است. با نام witness script و «معمای رمزنگاریشده» هم شناخته میشود. - اسکریپت باز: اسکریپتی که شرط قفل را «حل» میکند و در هر ورودی است؛ معمولاً امضای دیجیتال دارد. نام تاریخی
scriptSig، و در سگویت: witness.
نرمافزار اعتبارسنج اسکریپت باز ورودی را کپی میکند، UTXO ارجاعشده را میگیرد و اسکریپت قفلش را کپی میکند و هر دو را اجرا میکند. ورودیها مستقل از هم اعتبارسنجی میشوند. UTXO برای همیشه روی بلاکچین ثابت است و تلاش ناموفق برای خرج آن چیزی را تغییر نمیدهد؛ فقط تراکنش معتبر آن را «خرجشده» میکند و از UTXO set حذف میکند.
پشتهٔ اجرا
پشته (stack) ساختار LIFO با دو عمل push و pop است. Script عناصر را از چپ به راست پردازش میکند: ثابتهای داده push میشوند؛ عملگرها یک یا چند مقدار pop میکنند، روی آنها کار میکنند و گاهی نتیجه را push میکنند. مثلاً OP_ADD دو مقدار را pop و مجموعشان را push میکند؛ OP_EQUAL دو مقدار را pop و در صورت برابری TRUE (عدد ۱) و در غیر این صورت FALSE (صفر) push میکند. اسکریپتها معمولاً یک عملگر شرطی دارند تا نتیجهٔ TRUE بدهند.
یک اسکریپت ساده
مثال 2 3 OP_ADD 5 OP_EQUAL: ۲ و ۳ push میشوند، OP_ADD آنها را به ۵ تبدیل میکند، و OP_EQUAL برابری با ۵ را میسنجد. میتوان 3 OP_ADD 5 OP_EQUAL را اسکریپت قفل گذاشت که با اسکریپت باز 2 برآورده میشود؛ یعنی هر کس حساب بداند میتواند این UTXO را خرج کند. مثال پیچیدهتر: 2 7 OP_ADD 3 OP_SUB 1 OP_ADD 7 OP_EQUAL.
قاعدهٔ اعتبار: تراکنش وقتی معتبر است که بالای پشته TRUE باشد ({0x01}) یا هر مقدار غیرصفر دیگر، یا پشته پس از اجرا خالی باشد. وقتی نامعتبر است که بالای پشته FALSE (مقدار تهی {}) باشد، یا اجرا توسط عملگری مثل OP_VERIFY، OP_RETURN یا یک پایاندهندهٔ شرطی مانند OP_ENDIF صریحاً متوقف شود.
اجرای جداگانهٔ قفل و باز
در کلاینت اولیه، اسکریپت باز و قفل به هم الصاق و پشتسرهم اجرا میشدند. در سال ۲۰۱۰ به دلیل یک آسیبپذیری (اسکریپت باز مخرب میتوانست دادهای روی پشته بریزد و اسکریپت قفل را خراب کند) تغییر کرد. اکنون ابتدا اسکریپت باز اجرا میشود؛ اگر بدون خطا تمام شد، پشتهٔ اصلی (نه پشتهٔ جایگزین) کپی و اسکریپت قفل روی آن اجرا میشود. اگر نتیجه TRUE بود، ورودی معتبر است.
P2PKH — پرداخت به هش کلید عمومی
بیشتر تراکنشهای بیتکوین خروجیهایی با قفل Pay-to-Public-Key-Hash (P2PKH) دارند: خروجی به هش کلید عمومی قفل است (همان آدرس بیتکوین بدون کدگذاری Base58Check، که آدرسها با «۱» شروع میشوند). برای خرج، باید کلید عمومی و امضای متناظر با کلید خصوصی ارائه شود.
- اسکریپت قفل پرداخت آلیس به کافه:
OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG - اسکریپت باز:
<Cafe Signature> <Cafe Public Key> - اسکریپت ترکیبی:
<Sig> <PubKey> OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
اجرا (شکلهای ۶-۵ و ۶-۶): امضا و کلید عمومی push میشوند؛ OP_DUP کلید عمومی را کپی میکند؛ OP_HASH160 کپی را هش میکند؛ هش مورد انتظار push میشود؛ OP_EQUALVERIFY برابری دو هش را میسنجد (و در صورت ناهمخوانی اجرا را متوقف میکند)؛ و OP_CHECKSIG اعتبار امضا را روی کلید عمومی بررسی میکند. نتیجه فقط وقتی TRUE است که اسکریپت باز امضای معتبر از کلید خصوصی مربوط به هش قفل داشته باشد.
امضاهای دیجیتال (ECDSA)
بیتکوین از ECDSA (الگوریتم امضای دیجیتال منحنی بیضوی) استفاده میکند. عملگرهای OP_CHECKSIG، OP_CHECKSIGVERIFY، OP_CHECKMULTISIG و OP_CHECKMULTISIGVERIFY امضای ECDSA میطلبند. امضا سه کار انجام میدهد:
- اثبات اینکه مالک کلید خصوصی (و بنابراین وجوه) خرج را مجاز کرده است؛
- عدم انکار (nonrepudiation)؛
- اثبات اینکه تراکنش (یا بخشهای امضاشدهٔ آن) بعد از امضا تغییر نکرده و نمیکند (یکپارچگی).
هر ورودی مستقل امضا میشود؛ پس طرفهای مختلف میتوانند در ساخت یک تراکنش همکاری کنند و هرکدام فقط ورودی خود را امضا کنند. طرح CoinJoin برای حریم خصوصی از همین ویژگی استفاده میکند.
ساخت امضا
«پیام» تراکنش است، یا دقیقتر هش زیرمجموعهای از دادههای آن (بسته به SIGHASH). ورودی الگوریتم: کلید خصوصی امضاکننده (dA)، پیام (m)، تابع هش (Fhash) و الگوریتم امضا (Fsig)؛ خروجی جفت (R, S) است. این جفت با DER (Distinguished Encoding Rules) به جریان بایتی تبدیل میشود.
قالب DER در امضای آلیس
امضای ورودی آلیس نه عنصر دارد:
0x30: شروع دنباله؛0x45: طول دنباله (۶۹ بایت)؛0x02: عدد صحیح بعدی، با طول0x21(۳۳ بایت) که R است (با بایت پیشوند00)؛0x02: عدد صحیح بعدی، با طول0x20(۳۲ بایت) که S است؛- پسوند
0x01: نوع هش، یعنی SIGHASH_ALL.
راستیآزمایی امضا
برای تأیید به R و S، تراکنش سریالشده (یا بخشی از آن) و کلید عمومی نیاز است. معنای تأیید: «فقط مالک کلید خصوصیِ مربوط به این کلید عمومی میتوانسته این امضا را روی این تراکنش بسازد». الگوریتم TRUE یا FALSE برمیگرداند.
انواع هش امضا (SIGHASH)
امضا یعنی تعهد امضاکننده به دادههای خاصی از تراکنش. سادهترین حالت تعهد به کل تراکنش است، اما میتوان فقط به زیرمجموعهای متعهد شد. یک flag تکبایتی به انتهای امضا اضافه میشود و برای هر ورودی میتواند متفاوت باشد؛ بسیاری از حالتها فقط وقتی معنا دارند که چند نفر بیرون از شبکه روی تراکنش نیمهامضاشده همکاری کنند.
| SIGHASH | مقدار | توضیح |
|---|---|---|
| ALL | 0x01 |
همهٔ ورودیها و همهٔ خروجیها |
| NONE | 0x02 |
همهٔ ورودیها، هیچ خروجی |
| SINGLE | 0x03 |
همهٔ ورودیها و فقط خروجی هماندیس با ورودی امضاشده |
| ALL|ANYONECANPAY | 0x81 |
فقط یک ورودی، همهٔ خروجیها |
| NONE|ANYONECANPAY | 0x82 |
فقط یک ورودی، هیچ خروجی |
| SINGLE|ANYONECANPAY | 0x83 |
یک ورودی و خروجی هماندیس |
اصلاحگر ANYONECANPAY مقدار 0x80 دارد و با OR بیتی ترکیب میشود: فقط یک ورودی امضا میشود و بقیه (و sequenceهایشان) برای تغییر باز میمانند.
سازوکار: از تراکنش یک کپی گرفته میشود، بخشهایی خالی/کوتاه میشود، تراکنش حاصل سریال میشود، flag به انتها اضافه و کل هش میشود؛ این هش همان «پیام» امضاست. چون flag آخرین مرحله پیش از هش است، خود نوع SIGHASH هم در تعهد قرار میگیرد و (مثلاً توسط ماینر) قابل تغییر نیست. همهٔ انواع، فیلد nLocktime را هم امضا میکنند. امضای آلیس SIGHASH_ALL است که رایجترین شکل است.
کاربردهای عملی:
- ALL|ANYONECANPAY: تراکنش «جمعسپاری» (crowdfunding). جمعآورنده یک خروجی به مبلغ هدف میسازد (بدون ورودی و ناکافی)؛ هر حامی ورودی خود را اضافه و با این flag امضا میکند. تا وقتی مجموع ورودیها به هدف نرسد، تراکنش نامعتبر است و تعهدها قابل برداشت نیست.
- NONE: «چک در وجه حامل / چک سفید» با مبلغ مشخص؛ هر کس میتواند آدرس خود را در اسکریپت خروجی بنویسد، اما مقدار قفل است.
- NONE|ANYONECANPAY: «جمعکنندهٔ گرد و غبار» (dust collector)؛ UTXOهای بسیار ریز که کارمزد خرجشان از ارزششان بیشتر است، برای تجمیع توسط دیگران اهدا میشوند.
پیشنهادهایی هم برای گسترش SIGHASH وجود دارد، مثل Bitmask Sighash Modes از Glenn Willen (Blockstream، پروژهٔ Elements) که بیتماسکهای دلخواه برای ورودی/خروجی میدهد. کیف پولهای معمولی گزینهٔ SIGHASH ندارند؛ تقریباً همیشه P2PKH با SIGHASH_ALL میسازند و استفاده از انواع دیگر نیازمند نرمافزار اختصاصی است.
ریاضیات ECDSA
الگوریتم ابتدا یک جفت کلید موقتی (ephemeral) میسازد: عدد تصادفی k بهعنوان کلید خصوصی موقت و P = k·G کلید عمومی آن. R برابر مختصات x نقطهٔ P است. سپس:
S = k⁻¹ (Hash(m) + dA · R) mod p
که p مرتبهٔ اول منحنی است. تأیید معکوس همین است: با R، S و کلید عمومی Qa نقطهٔ P = S⁻¹·Hash(m)·G + S⁻¹·R·Qa محاسبه میشود؛ اگر مختصات x برابر R بود، امضا معتبر است. در این فرایند کلید خصوصی نه معلوم است و نه فاش میشود.
اهمیت تصادفیبودن
مقدار k باید تصادفی و یکتا باشد. اگر یک k برای دو امضا (دو تراکنش) استفاده شود، هر کسی میتواند کلید خصوصی را محاسبه کند. این خطر نظری نیست: در برخی پیادهسازیها کلید فاش و وجوه سرقت شده است؛ معمولترین علت، مولد عدد تصادفی با مقداردهی اولیهٔ نادرست است. بهترین رویکرد صنعت، بهجای مولد تصادفی مبتنی بر entropy، یک فرایند قطعی-تصادفی (deterministic) با بذر از دادهٔ خود تراکنش است تا هر تراکنش k متفاوت بگیرد. استاندارد آن RFC 6979 (از IETF) است و هر پیادهسازی امضا باید از آن یا معادلش استفاده کند.
آدرسها، موجودیها و سایر انتزاعها
دیدیم که تراکنش آدرس و موجودی صریح ندارد، پس کاربرد این مفاهیم در wallet و explorer چگونه ساخته میشود؟
- «فرستنده» در explorer: explorer تراکنش قبلی ارجاعشده در ورودی را میگیرد، خروجی اول را بیرون میکشد، میبیند قفل P2PKH است، هش کلید عمومی را استخراج میکند و با Base58Check به آدرس تبدیل میکند.
- گیرندهها: همین کار برای هر خروجی انجام میشود (اولی آدرس باب، دومی آدرس باقیمانده آلیس).
- Total Received: explorer آدرس باب را از Base58Check رمزگشایی میکند تا هش ۱۶۰ بیتی کلید عمومی به دست آید، سپس در پایگاه دادهٔ تراکنشها خروجیهای P2PKH با آن هش را جستجو و مقدارشان را جمع میکند.
- Final Balance: به پایگاه دادهٔ جداگانهای از UTXO set نیاز دارد که explorer باید لحظهبهلحظه با شبکه (از جمله تراکنشهای تأییدنشده) همگام نگه دارد و با اجماع شبکه همراستا بماند؛ گاهی از همگامی خارج میشود و دید ناقص یا غلط دارد. مجموع خروجیهای خرجنشدهٔ آن هش، موجودی نمایشدادهشده است.
- برای ساخت یک تصویر با دو «موجودی»، explorer باید دهها تا صدها هزار تراکنش را نمایهسازی و جستجو کند.
این انتزاعها بر رایجترین حالت (P2PKH با SIGHASH_ALL روی همهٔ ورودیها) تمرکز دارند و بیش از ۸۰٪ تراکنشها را خوانا نشان میدهند، اما در تراکنشهای غیرمعمول (قفل پیچیدهتر، SIGHASH متفاوت، ورودی/خروجی زیاد) میلنگند. هر روز صدها تراکنش بدون خروجی P2PKH تأیید میشود و explorerها اغلب با هشدار قرمز «آدرس قابل رمزگشایی نیست» نشانشان میدهند (مثل صفحهٔ «strange transactions»). اینها واقعاً عجیب نیستند، فقط اسکریپت قفل پیچیدهتری دارند؛ موضوع فصل بعد.
جمعبندی
- تراکنش بیتکوین مفاهیمی مثل حساب، آدرس، موجودی و فرستنده/گیرنده ندارد؛ فقط ورودیهایی که UTXOهای قبلی را با اسکریپت باز مصرف میکنند و خروجیهایی که مقدار (ساتوشی) و اسکریپت قفل دارند. تراکنش coinbase تنها استثنای بدون ورودی است.
- خروجیها تقسیمناپذیرند، پس باقیمانده لازم است؛ و کارمزد صریح نیست و از تفاضل مجموع ورودیها و خروجیها میآید (و بر اساس اندازه محاسبه میشود)، پس فراموشکردن خروجی باقیمانده یعنی بخشیدن آن به ماینر.
- Script زبان پشتهمحور، بدون حلقه، بدون حالت و ناتمامتورینگ است؛ اعتبار با TRUE ماندن بالای پشته پس از اجرای جداگانهٔ اسکریپت باز و سپس قفل (روی پشتهٔ کپیشده) تعیین میشود. رایجترین الگو P2PKH است.
- امضای ECDSA (با کدگذاری DER و flagهای SIGHASH) مالکیت، عدم انکار و یکپارچگی را تضمین میکند؛ هر ورودی مستقل امضا میشود و انواع SIGHASH کاربردهایی مثل جمعسپاری و CoinJoin را ممکن میکنند. تصادفیبودن k حیاتی است و باید از RFC 6979 استفاده کرد.
- آنچه کیف پولها و explorerها نشان میدهند، انتزاعهایی است که با بازیابی تراکنشهای قبلی، تجمیع UTXOها و رمزگشایی اسکریپتها ساخته میشود. فصل بعد اسکریپتهای پیشرفتهتر (چندامضایی، P2SH و …) را بررسی میکند.
فصل ۷ — تراکنشهای پیشرفته و اسکریپتنویسی (Advanced Transactions and Scripting)
مقدمه
فصل قبل ساختار پایهٔ تراکنش و رایجترین الگوی اسکریپت، یعنی P2PKH، را معرفی کرد. این فصل نشان میدهد با زبان اسکریپت بیتکوین چگونه میتوان شرطهای پیچیدهتری برای خرجکردن خروجیها تعریف کرد. ترتیب مطالب: ابتدا چندامضایی (multisig)، سپس دومین الگوی پرکاربرد یعنی Pay-to-Script-Hash (P2SH) که دنیای اسکریپتهای پیچیده را عملی میکند، بعد خروجی ثبت داده (RETURN)، سپس قفلهای زمانی (timelocks) که بُعد زمان را به بیتکوین اضافه میکنند، و در پایان کنترل جریان شرطی (IF/ELSE) و یک مثال ترکیبی کامل.
چندامضایی (Multisignature)
- اسکریپت قفل چندامضایی میگوید: N کلید عمومی در اسکریپت ثبت شده و برای باز کردن وجه، حداقل M امضا از میان آنها لازم است. به این طرح M-of-N میگویند؛ مثلاً ۲-از-۳ یعنی سه کلید ممکن و دستکم دو امضای معتبر.
- در زمان نگارش کتاب، اسکریپتهای چندامضایی استاندارد حداکثر ۱۵ کلید فهرستشده دارند (از ۱-از-۱ تا ۱۵-از-۱۵)؛ محدودیت دقیق را تابع
isStandard()تعیین میکند و ممکن است عوض شود. - شکل کلی اسکریپت قفل:
M <PubKey 1> ... <PubKey N> N CHECKMULTISIG - مثال ۲-از-۳:
2 <A> <B> <C> 3 CHECKMULTISIG. اسکریپت باز با دو امضای متناظر دو تا از این سه کلید ارضا میشود، مثلاً<Sig B> <Sig C>(هر ترکیب دوتایی دیگر هم معتبر است). - اسکریپت قفل و باز پشتسرهم اجرا میشوند و فقط وقتی نتیجه TRUE است که امضاها با کلیدهای فهرستشده بخوانند.
باگ CHECKMULTISIG
- طبق منطق،
CHECKMULTISIGباید M+N+2 آیتم از پشته مصرف کند. اجرا چنین است: ابتدا N را برمیدارد، سپس N کلید عمومی، بعد M (حدنصاب)، و بعد باید M امضا را بردارد. - اما به خاطر یک باگ پیادهسازی، یک آیتم اضافه هم از پشته برمیدارد. این آیتم نادیده گرفته میشود، ولی اگر وجود نداشته باشد پشته خالی میشود و اسکریپت شکست میخورد.
- چون این باگ بخشی از قواعد اجماع شده است، باید برای همیشه حفظ شود. قرارداد این است که یک
0بهعنوان آیتم ساختگی در ابتدای اسکریپت باز بگذارند:0 <Sig B> <Sig C>. بنابراین هر وقت در اسکریپت باز چندامضایی یک صفر اضافی دیدید، دلیلش همین راهحل است.
Pay-to-Script-Hash (P2SH)
P2SH در سال ۲۰۱۲ معرفی شد تا استفاده از اسکریپتهای پیچیده ساده شود.
انگیزه: مثال محمد در دبی
شرکت واردات الکترونیک محمد برای حسابهای دریافتنی خود چندامضایی ۲-از-۵ به کار میبرد (کلید محمد، سه شریک و وکیل شرکت که کلید پشتیبان دارد). اسکریپت حاصل بلند است: 2 <Mohammed> <Partner1> <Partner2> <Partner3> <Attorney> 5 CHECKMULTISIG. مشکلات استفادهٔ مستقیم:
- محمد باید این اسکریپت را به هر مشتری بدهد.
- هر مشتری به کیف پولی نیاز دارد که اسکریپت سفارشی بسازد و بلد باشد چنین تراکنشی را بسازد.
- تراکنش حدود ۵ برابر یک پرداخت ساده بزرگ میشود (کلیدهای عمومی بلندند) و کارمزد آن بر دوش مشتری میافتد.
- اسکریپت بلند تا زمان خرجشدن در مجموعهٔ UTXO و حافظهٔ RAM همهٔ گرههای کامل میماند.
راهحل: جایگزینی اسکریپت با اثرانگشت آن
در P2SH اسکریپت قفل پیچیده با یک هش رمزنگاریشده جایگزین میشود. اسکریپت اصلی را redeem script (اسکریپت بازخرید) مینامند چون در زمان خرجکردن ارائه میشود، نه هنگام قفلکردن.
| بدون P2SH | با P2SH | |
|---|---|---|
| Redeem script | — | 2 PK1 … PK5 5 CHECKMULTISIG |
| اسکریپت قفل | 2 PK1 … PK5 5 CHECKMULTISIG |
HASH160 <هش ۲۰ بایتی redeem script> EQUAL |
| اسکریپت باز | Sig1 Sig2 |
Sig1 Sig2 <redeem script> |
- هش ۲۰ بایتی با اعمال SHA256 و سپس RIPEMD160 (یعنی HASH160) روی redeem script به دست میآید. در مثال کتاب هش این اسکریپت
54c557e0…e97eاست. - مشتری فقط خروجی کوتاه
HASH160 <hash> EQUALرا میسازد؛ یعنی «به اسکریپتی بپرداز که هشش این است».
اعتبارسنجی دو مرحلهای
هنگام خرجکردن، اعتبارسنجی در دو مرحله انجام میشود:
- مرحلهٔ اول: redeem script ارائهشده هش میشود و باید با هش داخل اسکریپت قفل برابر باشد:
<redeem script> HASH160 <hash> EQUAL. - مرحلهٔ دوم: اگر برابر بود، redeem script اجرا میشود و امضاها در برابر آن بررسی میشوند:
<Sig1> <Sig2> 2 PK1 … PK5 5 CHECKMULTISIG.
نکتهٔ مهم: بیشتر اسکریپتهای پیچیدهٔ این فصل فقط بهصورت P2SH قابل استفادهاند و نمیشود آنها را مستقیم در اسکریپت قفل یک UTXO گذاشت.
آدرسهای P2SH
- طبق BIP-13، هش اسکریپت با Base58Check کدگذاری میشود، درست مثل آدرسهای معمول که کدگذاری هش کلید عمومیاند.
- پیشوند نسخه برابر
5است و آدرس حاصل با3شروع میشود؛ مثلاً آدرس اسکریپت محمد39RF6JqABiHdYHkfChV6USGMe6Nsr66Gzwمیشود. - مشتری با تقریباً هر کیف پولی مثل یک پرداخت عادی به این آدرس میپردازد؛ پیچیدگی از دید پرداختکننده پنهان است و فقط پیشوند
3نشان میدهد که آدرس متعلق به یک اسکریپت است نه یک کلید.
مزایای P2SH
- اسکریپتهای پیچیده با اثرانگشت کوتاه جایگزین میشوند و تراکنش کوچکتر میشود.
- اسکریپت را میتوان به شکل آدرس درآورد؛ فرستنده و کیف پولش نیازی به مهندسی پیچیده ندارند.
- بار ساختن اسکریپت از فرستنده به گیرنده منتقل میشود.
- بار ذخیرهسازی از خروجی (که در مجموعهٔ UTXO میماند) به ورودی (که فقط در بلاکچین ذخیره میشود) میرود.
- بار ذخیرهسازی از زمان پرداخت به زمان آیندهٔ خرجکردن منتقل میشود.
- هزینهٔ کارمزد اسکریپت بلند از فرستنده به گیرنده (خرجکننده) میرسد.
redeem script و اعتبارسنجی؛ هشدارها
- پیش از Bitcoin Core نسخهٔ ۰٫۹٫۲، redeem script فقط میتوانست از انواع استاندارد باشد (P2PK، P2PKH، چندامضایی؛ نه RETURN و نه خود P2SH). از نسخهٔ ۰٫۹٫۲ به بعد هر اسکریپت معتبری مجاز است، که راه را برای آزمایش انواع جدید تراکنش باز کرد.
- P2SH بازگشتی نیست: نمیتوان P2SH را داخل redeem script دیگری گذاشت. گذاشتن RETURN در redeem script هم از نظر فنی ممکن است ولی بیفایده است، چون اجرای آن در اعتبارسنجی تراکنش را نامعتبر میکند.
- خطر: چون redeem script تا لحظهٔ خرجکردن به شبکه نشان داده نمیشود، میتوان وجه را با هش یک اسکریپت نامعتبر قفل کرد. شبکه چنین خروجیای را میپذیرد، اما هیچ تراکنش خرجکنندهای هرگز معتبر نخواهد بود و بیتکوین برای همیشه از دست میرود. هش هیچ سرنخی از محتوای اسکریپت نمیدهد.
خروجی ثبت داده (RETURN)
- بلاکچین بیتکوین بهعنوان دفتر کل زماندار و توزیعشده کاربردهایی فراتر از پرداخت دارد؛ مثلاً خدمات سندنگاری دیجیتال (ثبت اثرانگشت یک فایل برای اثبات وجود آن در تاریخ مشخص)، گواهی سهام و قرارداد هوشمند. تلاشهای اولیه برای این کار خروجیهایی میساختند که داده را روی زنجیره ثبت میکردند.
- بحث: منتقدان آن را سوءاستفاده و باعث «ورم بلاکچین» (blockchain bloat) میدانند، چون گرههای کامل هزینهٔ دیسک را میپردازند. بدتر، روش قدیمی آدرس مقصد را بهعنوان فیلد ۲۰ بایتی دلخواه به کار میبرد؛ چنین خروجیای کلید خصوصی ندارد، هرگز خرج نمیشود و برای همیشه در مجموعهٔ UTXO میماند و آن را بزرگ میکند.
- سازش: در Bitcoin Core نسخهٔ ۰٫۹ عملگر RETURN (OP_RETURN) آمد که اجازهٔ افزودن ۸۰ بایت داده غیرپرداختی به یک خروجی را میدهد. این خروجی صریحاً و بهاثباترسیده خرجنشدنی (provably unspendable) است و نیازی نیست در مجموعهٔ UTXO نگه داشته شود؛ فقط در بلاکچین (دیسک) جا میگیرد و فشار RAM روی گرهها وارد نمیکند.
- شکل:
RETURN <data>؛ داده معمولاً یک هش است (مثلاً خروجی ۳۲ بایتی SHA256). بسیاری از برنامهها پیشوندی برای شناسایی میگذارند؛ مثلاً سرویس Proof of Existence پیشوند ۸ بایتیDOCPROOF(به هگز:44 4f 43 50 52 4f 4f 46) به کار میبرد. - هیچ اسکریپت بازی برای RETURN وجود ندارد. مقدار خروجی معمولاً صفر است، چون هر بیتکوینی که به آن تخصیص یابد برای همیشه از بین میرود. اگر تراکنشی چنین خروجیای را بهعنوان ورودی ارجاع دهد، موتور اعتبارسنجی اجرا را متوقف و تراکنش را نامعتبر اعلام میکند (اجرای RETURN یعنی بازگشت با FALSE).
- یک تراکنش استاندارد (قابلقبول برای
isStandard()) فقط میتواند یک خروجی RETURN داشته باشد، ولی آن را میتوان با خروجیهای هر نوع دیگر ترکیب کرد. - از Bitcoin Core ۰٫۱۰ دو گزینهٔ خط فرمان اضافه شد:
datacarrier(پیشفرض1، یعنی رله و استخراج مجاز) وdatacarriersize(پیشفرض ۸۳ بایت = ۸۰ بایت داده + ۱ بایت opcode RETURN + ۲ بایت PUSHDATA). - یادداشت تاریخی: سقف ابتدا ۸۰ بایت پیشنهاد شد، هنگام انتشار به ۴۰ بایت کاهش یافت و در فوریهٔ ۲۰۱۵ (نسخهٔ ۰٫۱۰) دوباره ۸۰ شد. گرهها میتوانند RETURN را رله یا استخراج نکنند یا فقط نمونههای کوچکتر را بپذیرند.
قفلهای زمانی (Timelocks)
قفل زمانی محدودیتی روی تراکنش یا خروجی است که خرجکردن را فقط بعد از یک نقطهٔ زمانی مجاز میکند. بیتکوین از ابتدا قفل زمانی در سطح تراکنش داشت (nLocktime) و دو قابلیت جدید در سطح UTXO در اواخر ۲۰۱۵ و میانهٔ ۲۰۱۶ اضافه شد: CHECKLOCKTIMEVERIFY و CHECKSEQUENCEVERIFY. کاربردها: تاریخگذاری آیندهنگر تراکنشها، قفل وجه تا یک تاریخ، و مهمتر از همه، گسترش اسکریپت به بُعد زمان که قراردادهای هوشمند چندمرحلهای را ممکن میکند.
قفل زمانی تراکنش (nLocktime)
- فیلدی در ساختار تراکنش که زودترین زمان معتبر بودن آن را تعیین میکند. در بیشتر تراکنشها صفر است (انتشار و اجرای فوری).
- تفسیر مقدار: اگر ناصفر و کمتر از ۵۰۰ میلیون باشد، ارتفاع بلاک است؛ اگر بیشتر از ۵۰۰ میلیون باشد، یک Unix Epoch timestamp (ثانیهها از ۱ ژانویهٔ ۱۹۷۰) است.
- تراکنشی که nLocktime آینده دارد باید نزد سازندهاش نگه داشته شود و بعد از معتبر شدن به شبکه فرستاده شود؛ اگر زودتر پخش شود، اولین گره آن را نامعتبر رد میکند و رله نمیشود. مثل چک تاریخدار.
محدودیت nLocktime
مثال: آلیس تراکنشی به آدرس باب امضا میکند، nLocktime آن را سه ماه بعد میگذارد و به باب میدهد. تضمینها: باب تا سه ماه نمیتواند آن را پخش کند و بعد از آن میتواند. اما آلیس هنوز میتواند همان ورودیها را در تراکنش دیگری بدون قفل زمانی دوبارهخرج (double spending) کند و باب هیچ تضمینی ندارد که این کار را نکند. تنها تضمین این است که باب زودتر برداشت نمیکند، نه اینکه وجه را حتماً میگیرد. برای تضمین واقعی، قفل زمانی باید روی خود UTXO و در اسکریپت قفل باشد، که کار CLTV است.
CHECKLOCKTIMEVERIFY (CLTV) — BIP-65
- در دسامبر ۲۰۱۵ بهصورت فورک نرم اضافه شد. قفل زمانی به ازای هر خروجی است، نه هر تراکنش.
- CLTV جایگزین nLocktime نیست؛ UTXOهای خاصی را محدود میکند تا فقط در تراکنشی خرج شوند که nLocktime آن بزرگتر یا مساوی مقدار CLTV باشد.
- یک پارامتر میگیرد با همان فرمت nLocktime (ارتفاع بلاک یا زمان Unix). پسوند VERIFY یعنی اگر نتیجه FALSE باشد اجرا متوقف میشود.
- مثال: بهجای P2PKH معمولی
DUP HASH160 <Bob PKH> EQUALVERIFY CHECKSIG، آلیس بهصورت P2SH با redeem script زیر قفل میکند:<now + 3 months> CHECKLOCKTIMEVERIFY DROP DUP HASH160 <Bob PKH> EQUALVERIFY CHECKSIGبرای سه ماه تقریباً «ارتفاع فعلی + ۱۲٬۹۶۰ بلاک» یا «زمان Unix فعلی + ۷٬۷۶۰٬۰۰۰ ثانیه» به کار میرود.
- باب برای خرجکردن، تراکنشی میسازد که nLocktime آن مساوی یا بزرگتر از قفل آلیس است، با امضا و کلید عمومی خودش. اگر پارامتر CLTV ≤ nLocktime تراکنش خرجکننده باشد، اجرا ادامه مییابد (مثل NOP)، وگرنه تراکنش نامعتبر است.
- شرایط شکست CLTV طبق BIP-65:
- پشته خالی باشد؛
- مقدار بالای پشته منفی باشد؛
- نوع قفل (ارتفاع در برابر زمان) در پشته و nLocktime یکی نباشد؛
- مقدار بالای پشته از nLocktime تراکنش بزرگتر باشد؛
- فیلد
nSequenceورودی برابر0xffffffffباشد.
- پس از CLTV، مقدار زمان روی پشته میماند و معمولاً باید با
DROPحذف شود؛ به همین دلیلCHECKLOCKTIMEVERIFY DROPرا اغلب پشتسرهم میبینید. - نتیجه: با ترکیب nLocktime و CLTV، سناریوی بالا عوض میشود. چون خود UTXO قفل شده است، تا پایان سه ماه نه باب و نه آلیس نمیتوانند آن را خرج کنند.
قفلهای زمانی نسبی (Relative Timelocks)
nLocktime و CLTV هر دو مطلق هستند (نقطهٔ مشخصی از زمان). قفل نسبی شرط خرجکردن را بر اساس زمان سپریشده از تأیید خروجی در بلاکچین تعریف میکند. این برای زنجیرهای از تراکنشهای وابسته که خارج از زنجیره نگه داشته میشوند مفید است، چون ساعت فقط وقتی شروع میشود که UTXO در بلاکچین ثبت شود. مهمترین کاربرد: کانالهای پرداخت و حالت دوطرفه و شبکهٔ Lightning. پیادهسازی در دو سطح است: یک قاعدهٔ اجماع روی nSequence در سطح تراکنش، و opcode به نام CSV در سطح اسکریپت. مشخصات در BIP-68 و BIP-112 است و هر دو در مه ۲۰۱۶ بهصورت فورک نرم فعال شدند.
قفل نسبی با nSequence — BIP-68
- معنای اصلی (هرگز کامل پیادهسازی نشد): nSequence قرار بود امکان جایگزینی تراکنش در mempool را بدهد. ورودی با مقدار کمتر از 2^32 یعنی تراکنش هنوز «نهایی» نشده و میتواند با تراکنش دیگری با nSequence بالاتر جایگزین شود؛ مقدار 2^32−1 یعنی نهایی و قابل استخراج. در عمل، تراکنشهای بدون قفل زمانی مقدار 0xFFFFFFFF میگذارند.
- برای کارکرد nLocktime یا CLTV، nSequence باید کمتر از 2^32−1 باشد؛ رسم است
0xFFFFFFFEگذاشته شود. - قاعدهٔ BIP-68: اگر بیت پرارزش (1<<31) در nSequence یک ورودی صفر باشد، این ورودی قفل زمانی نسبی دارد؛ اگر یک باشد، مقدار برای کاربردهای دیگر (nLocktime، CLTV، Opt-In RBF و آینده) رزرو است. یعنی nSequence < 2^31 به معنای قفل نسبی است.
- تراکنش فقط وقتی معتبر است که ورودی به اندازهٔ قفل نسبی «پیر» شده باشد؛ مثلاً nSequence معادل ۳۰ بلاک یعنی تراکنش تنها بعد از گذشت دستکم ۳۰ بلاک از استخراج UTXO ارجاعشده معتبر است. چون nSequence برای هر ورودی جداست، یک تراکنش میتواند ورودیهای قفلشده و بدون قفل را ترکیب کند، ولی همهٔ ورودیهای قفلدار باید بهاندازهٔ کافی پیر شده باشند.
- واحد: بیت نوع (type-flag) در بیت بیستوسوم از کمارزشترین (مقدار 1<<22) است. اگر برقرار باشد، مقدار nSequence ضریبی از ۵۱۲ ثانیه است؛ اگر نه، تعداد بلاک.
- فقط ۱۶ بیت کمارزش بهعنوان مقدار در نظر گرفته میشود و معمولاً با ماسک
nSequence & 0x0000FFFFجدا میشود.
قفل نسبی با CSV — BIP-112
CHECKSEQUENCEVERIFYوقتی در redeem script یک UTXO ارزیابی شود، فقط تراکنشی را قبول میکند که nSequence ورودی آن بزرگتر یا مساوی پارامتر CSV باشد؛ یعنی خرجکردن تا گذشت تعداد مشخصی بلاک یا ثانیه از زمان استخراج UTXO ممنوع میماند.- مانند CLTV، فرمت پارامتر باید با nSequence یکی باشد: اگر CSV بر حسب بلاک است، nSequence هم بلاک باشد؛ اگر ثانیه، هر دو ثانیه.
- مناسب وقتی چند تراکنش زنجیرهای ساخته و امضا میشوند اما پخش نمیشوند (خارج از زنجیره): تراکنش فرزند تا وقتی والد پخش، استخراج و به اندازهٔ قفل نسبی پیر نشده قابل استفاده نیست. این الگو در کانالهای پرداخت و Lightning به کار میرود.
Median-Time-Past — BIP-113
- در بیتکوین بین «زمان دیوار» (wall time) و «زمان اجماع» تفاوت ظریف ولی مهمی وجود دارد. ماینرها timestamp بلاک را میگذارند و قواعد اجماع کمی انعطاف دارند؛ این برای ماینر انگیزه میسازد که زمان را دروغ بگوید تا تراکنشهای قفلشدهای را که هنوز نرسیدهاند وارد بلاک کند و کارمزدشان را بگیرد.
- BIP-113 همزمان با قفلهای نسبی فعال شد و Median-Time-Past را تعریف میکند: میانهٔ timestamp ۱۱ بلاک اخیر، که زمان اجماع برای همهٔ محاسبات قفل زمانی است. چون نقطهٔ میانی تقریباً دو ساعت در گذشته است، اثر هر بلاک منفرد کم میشود و هیچ ماینر تنهایی نمیتواند زمان را دستکاری کند.
- اثر روی nLocktime، CLTV، nSequence و CSV: زمان اجماع همیشه تقریباً یک ساعت عقبتر از ساعت واقعی است، و هنگام تخمین مقدار قفلها باید آن را لحاظ کرد.
دفاع قفل زمانی در برابر Fee Sniping
- Fee sniping یک حملهٔ نظری است: ماینرهایی که قصد بازنویسی بلاکهای گذشته را دارند تراکنشهای پرکارمزد را «شکار» میکنند. مثلاً اگر بالاترین بلاک ۱۰۰٬۰۰۰ باشد، بهجای استخراج ۱۰۰٬۰۰۱ ممکن است برخی دوباره ۱۰۰٬۰۰۰ را استخراج کنند و از mempool هر تراکنش پرکارمزدی را در آن بگذارند.
- امروز این حمله سودآور نیست چون پاداش بلاک خیلی بیشتر از مجموع کارمزدهاست، ولی در آینده که کارمزدها بخش عمده یا کل پاداش شوند، اجتنابناپذیر میشود.
- دفاع: Bitcoin Core بهطور پیشفرض nLocktime همهٔ تراکنشهای جدید را روی «ارتفاع فعلی + ۱» میگذارد (و nSequence ورودیها را
0xFFFFFFFEتا nLocktime اثر کند). در حالت عادی بیاثر است چون تراکنش فقط در بلاک بعدی میتوانست بیاید؛ ولی در حملهٔ فورک ماینرها نمیتوانند تراکنشهای mempool را در بلاک بازنویسیشده بگذارند، چون همه قفل ارتفاع ۱۰۰٬۰۰۱ دارند.
اسکریپتها با کنترل جریان (Conditional Clauses)
- opcodeهای شرطی
IF،ELSE،ENDIFوNOTIFاجازه میدهند redeem script دو (یا چند) مسیر باز شدن داشته باشد که بسته به نتیجهٔ یک شرط منطقی انتخاب میشود. این شرطها تو در تو میشوند و میتوانند با عملگرهایBOOLAND،BOOLORوNOTترکیب شوند. نوشتن صدها یا هزاران مسیر ممکن است؛ محدودیت فقط حداکثر اندازهٔ بایتی اسکریپت در قواعد اجماع است. - چون اسکریپت بیتکوین مبتنی بر پشته است، شرط قبل از IF میآید (مثل
1 1 ADD): ابتدا condition، سپسIF … ELSE … ENDIF.
VERIFY در برابر IF
- opcodeهایی که به VERIFY ختم میشوند (مثل
EQUALVERIFY) نتیجه را روی پشته نمیگذارند و اگر شرط درست نباشد اجرا بلافاصله متوقف و تراکنش نامعتبر میشود؛ یعنی guard clause (شرط پیشنیاز) هستند. در مقابلEQUALنتیجه را روی پشته باقی میگذارد. - مثال:
HASH160 <expected hash> EQUALVERIFY <Bob PubKey> CHECKSIGبا اسکریپت باز<Bob Sig> <hash pre-image>: بدون ارائهٔ پیشتصویر (راز) هش، به بخش بررسی امضا نمیرسد. معادل با IF:HASH160 <hash> EQUAL IF <Bob PubKey> CHECKSIG ENDIFاست، ولی نسخهٔ VERIFY یک opcode کمتر دارد. - قاعده: اگر فقط پیششرط میخواهید، VERIFY بهتر است؛ اگر چند مسیر اجرا میخواهید، IF/ELSE لازم است.
مسیرهای چندگانه
- مثال: آلیس یا باب هر کدام بتواند خرج کند (معادل ۱-از-۲):
IF <Alice PubKey> CHECKSIG ELSE <Bob PubKey> CHECKSIG ENDIF - شرط در redeem script نیست؛ در اسکریپت باز تأمین میشود تا خرجکننده مسیر را «انتخاب» کند. آلیس:
<Alice Sig> 1(TRUE، مسیر اول)؛ باب:<Bob Sig> 0(FALSE، مسیر ELSE). - در IF تو در تو، اسکریپت باز دنبالهای از TRUE/FALSE بهعنوان «نقشه» میدهد. مثلاً برای انتخاب مسیر B در ساختار
IF A ELSE (IF B ELSE C) ENDIFباید اسکریپت باز با1 0تمام شود؛ مقدار FALSE که بالاتر است ابتدا توسط IF بیرونی برداشته میشود (ELSE)، سپس TRUE توسط IF داخلی مصرف میشود (مسیر B).
مثال پیچیده: حساب سرمایهٔ شرکت محمد
محمد، دو شریکش سعید و زائیرا، و وکیل شرکت عبدل، میخواهند حساب سرمایهای با قواعد متغیر بر پایهٔ قفل زمانی بسازند: تصمیم با اکثریت (۲ از ۳ شریک)؛ اگر مشکلی با کلیدها بود، وکیل با یکی از شرکا بتواند وجه را بازیابی کند؛ و اگر همهٔ شرکا مدتی در دسترس نبودند، وکیل بهتنهایی بتواند مدیریت کند. اسکریپت (با ساختار IF تو در تو):
IF
IF
2
ELSE
<30 days> CHECKSEQUENCEVERIFY DROP
<Abdul PubKey> CHECKSIGVERIFY
1
ENDIF
<Mohammed> <Saeed> <Zaira> 3 CHECKMULTISIG
ELSE
<90 days> CHECKSEQUENCEVERIFY DROP
<Abdul PubKey> CHECKSIG
ENDIF
| مسیر | شرط | اسکریپت باز |
|---|---|---|
| ۱ | ۲-از-۳ شرکا؛ هر زمان | 0 <Mohammed Sig> <Zaira Sig> TRUE TRUE |
| ۲ | بعد از ۳۰ روز؛ امضای عبدل + یکی از شرکا (۱-از-۳) | 0 <Saeed Sig> <Abdul Sig> FALSE TRUE |
| ۳ | بعد از ۹۰ روز؛ عبدل بهتنهایی | <Abdul Sig> FALSE |
- مسیر اول: حدنصاب multisig برابر ۲ میشود؛ صفر ابتدایی همان راهحل باگ CHECKMULTISIG است.
- مسیر دوم: CSV تضمین میکند ۳۰ روز از ساخت UTXO گذشته باشد، سپس امضای عبدل با
CHECKSIGVERIFYبررسی میشود و حدنصاب multisig برابر ۱ میشود. - ترتیب «FALSE TRUE» برعکس به نظر میرسد، اما چون FALSE ابتدا و TRUE بعد روی پشته میروند، IF بیرونی ابتدا TRUE را برمیدارد.
- مسیر سوم: CSV با ۹۰ روز و فقط امضای وکیل.
کتاب در پایان چند پرسش برای تمرین میپرسد: چرا وکیل نمیتواند مسیر سوم را در هر زمان با FALSE انتخاب کند؟ در روزهای ۵، ۳۵ و ۱۰۵ پس از استخراج UTXO چند مسیر قابل استفاده است؟ اگر وکیل کلیدش را گم کند وجه از دست میرود، و آیا پس از روز ۹۱ جواب فرق میکند؟ شرکا چگونه میتوانند هر ۲۹ یا ۸۹ روز «ساعت را ریست» کنند (با خرجکردن وجه به یک UTXO جدید) تا وکیل به وجه دسترسی نیابد؟ و چرا برخی CHECKSIGها پسوند VERIFY دارند و برخی ندارند (چون در مسیر دوم، CHECKSIG باید قبل از CHECKMULTISIG نهایی نتیجهاش را روی پشته نگذارد)؟
جمعبندی
- چندامضایی (M-of-N با
CHECKMULTISIG، تا ۱۵ کلید استاندارد) کنترل مشترک روی وجه را ممکن میکند؛ باگ پشتهٔ اضافه باعث شده اسکریپت باز همیشه با یک0شروع شود. - P2SH (BIP-13، آدرسهای با پیشوند
3) اسکریپت پیچیده را با هش ۲۰ بایتی جایگزین میکند و بار اندازه، کارمزد و ذخیرهسازی را به گیرنده و زمان خرجکردن منتقل میکند؛ اعتبارسنجی دو مرحلهای دارد و در صورت قفل با هش اسکریپت نامعتبر ممکن است وجه برای همیشه از دست برود. - RETURN تا ۸۰ بایت داده (سقف رله پیشفرض ۸۳ بایت) را در خروجی بهاثباترسیده خرجنشدنی ثبت میکند، بدون سنگینکردن مجموعهٔ UTXO.
- قفل زمانی مطلق: nLocktime (سطح تراکنش، آستانهٔ ۵۰۰ میلیون بین ارتفاع و زمان) و CLTV (BIP-65، سطح خروجی، با
DROPو شرط nSequence ≠0xffffffff). قفل زمانی نسبی: nSequence (BIP-68، بیت ۳۱، بیت نوع ۲۲، واحد ۵۱۲ ثانیه، ماسک ۱۶ بیتی) و CSV (BIP-112). کاربرد کلیدی: کانالهای پرداخت و Lightning. - Median-Time-Past (BIP-113، میانهٔ ۱۱ بلاک، حدود یک ساعت عقبتر از ساعت واقعی) انگیزهٔ دستکاری زمان توسط ماینرها را از بین میبرد؛ پیشفرض Bitcoin Core برای nLocktime در برابر fee sniping دفاع میکند.
- کنترل جریان (IF/ELSE/ENDIF/NOTIF) و opcodeهای VERIFY، چندین مسیر باز کردن در یک UTXO میسازند که خرجکننده با اسکریپت باز انتخاب میکند؛ مثال شرکت محمد سه مسیر اکثریت شرکا، شرکا + وکیل بعد از ۳۰ روز و وکیل تنها بعد از ۹۰ روز را ترکیب میکند.
فصل ۸ — شبکهٔ بیتکوین (The Bitcoin Network)
معماری شبکهٔ همتابههمتا (Peer-to-Peer)
بیتکوین بر بستر اینترنت بهصورت یک شبکهٔ همتابههمتا (P2P) ساخته شده است. معنایش این است که رایانههای شرکتکننده همه همارزشاند: گرهٔ «ویژه» یا سرور مرکزی وجود ندارد، سلسلهمراتبی در کار نیست و بار ارائهٔ خدمات شبکه بین همهٔ گرهها تقسیم میشود. گرهها در یک شبکهٔ مش با توپولوژی «تخت» به هم وصلاند و هر گره هم خدمت میدهد و هم مصرف میکند؛ انگیزهٔ مشارکت، همین «معامله به مثل» است. چنین شبکههایی ذاتاً مقاوم، غیرمتمرکز و باز هستند.
- نمونهٔ شاخص این معماری، اینترنت در روزهای نخست بود که گرههای IP برابر بودند؛ اینترنت امروز سلسلهمراتبیتر است ولی پروتکل اینترنت هنوز ماهیت تخت خود را حفظ کرده است.
- موفقترین کاربرد دیگر فناوری P2P، اشتراک فایل است: Napster پیشگام و BitTorrent تازهترین تکامل آن بود.
- انتخاب این معماری فقط یک گزینهٔ فنی نیست؛ بیتکوین ذاتاً یک پول نقد دیجیتال P2P است و عدم تمرکز کنترل اصل طراحی آن است که تنها با یک شبکهٔ اجماع تخت و غیرمتمرکز قابل دستیابی و نگهداری است.
عبارت «شبکهٔ بیتکوین» به مجموعهٔ گرههایی گفته میشود که پروتکل P2P بیتکوین را اجرا میکنند. پروتکلهای دیگری هم هستند، مثل Stratum برای استخراج و کیف پولهای سبک/موبایلی. این پروتکلها از طریق سرورهای دروازه (gateway) به شبکهٔ اصلی وصل میشوند: سرور دروازه با پروتکل P2P بیتکوین با شبکه حرف میزند و آن را برای گرههایی که پروتکل دیگری میفهمند (مثلاً ماینرهای Stratum) گسترش میدهد. مجموع اینها را کتاب «شبکهٔ گسترشیافتهٔ بیتکوین» (extended bitcoin network) مینامد.
انواع گره و نقشها
هر گره در شبکهٔ P2P با وجود برابری، بسته به عملکردهایی که ارائه میدهد نقشهای متفاوتی دارد. یک گرهٔ بیتکوین ترکیبی از چهار عملکرد است:
| عملکرد | نماد در شکل | توضیح |
|---|---|---|
| مسیریابی شبکه (Network Routing) | N | همهٔ گرهها دارند: اعتبارسنجی و پخش تراکنشها و بلاکها، کشف و حفظ اتصال به همتاها |
| پایگاهدادهٔ کامل بلاکچین (Full Blockchain) | B | نسخهٔ کامل و بهروز بلاکچین |
| استخراج (Miner) | M | رقابت برای ساخت بلاک جدید با سختافزار تخصصی و حل الگوریتم اثبات کار |
| کیف پول (Wallet) | W | خدمات کیف پول کاربر |
- گره کامل (full node): نسخهٔ کامل بلاکچین را نگه میدارد و میتواند هر تراکنشی را مستقل و معتبر، بدون ارجاع به منبع بیرونی، راستیآزمایی کند.
- گرهٔ SPV یا سبک (lightweight): فقط زیرمجموعهای از بلاکچین را نگه میدارد و تراکنش را با روش تأیید پرداخت سادهشده (Simplified Payment Verification) بررسی میکند.
- گرهٔ ماینر: بعضی ماینرها گره کاملاند و بعضی سبکاند و در استخراج مشترک (pool mining) به سرور استخر وابستهاند که خودش گره کامل را نگه میدارد.
- کیف پول کاربر: در کلاینت دسکتاپ معمولاً بخشی از گره کامل است؛ اما کیف پولهای روی دستگاههای محدود (گوشی هوشمند) بیشتر و بیشتر گرهٔ SPV هستند.
علاوه بر اینها سرورها و گرههایی با پروتکلهای تخصصی (مثل پروتکلهای استخر استخراج و دسترسی کلاینت سبک) نیز وجود دارند.
شبکهٔ گسترشیافتهٔ بیتکوین
- شبکهٔ اصلی P2P (در زمان نگارش) شامل ۵٬۰۰۰ تا ۸٬۰۰۰ گرهٔ شنوا (listening) است که نسخههای مختلف کلاینت مرجع Bitcoin Core را اجرا میکنند، بهعلاوهٔ چند صد گره با پیادهسازیهای دیگر مانند Bitcoin Classic، Bitcoin Unlimited، BitcoinJ، Libbitcoin، btcd و bcoin.
- درصد کمی از این گرهها ماینر هستند (تأیید تراکنش و ساخت بلاک).
- شرکتهای بزرگ با اجرای کلاینتهایی بر پایهٔ Bitcoin Core، گره کامل بدون استخراج و کیف پول راه میاندازند. این گرهها مانند روترهای لبهٔ شبکهاند و سرویسهای دیگر (صرافیها، کیف پولها، کاوشگر بلاک، پردازش پرداخت فروشندگان) روی آنها بنا میشود.
- به شبکهٔ اصلی تعدادی سرور استخر و دروازهٔ پروتکل وصل است که گرههای پروتکلهای دیگر را متصل میکنند؛ این گرهها عمدتاً ماینرهای استخر (فصل ۱۰) و کلاینتهای کیف پول سبکاند که نسخهٔ کامل بلاکچین ندارند.
شبکههای رله بیتکوین (Bitcoin Relay Networks)
شبکهٔ P2P معمولی برای نیاز عمومی انواع گره مناسب است، اما تأخیر آن برای ماینرها زیاد است. ماینرها در رقابتی زمانحساس برای حل اثبات کار هستند و باید فاصلهٔ بین انتشار بلاک برنده و شروع دور بعدی رقابت را حداقل کنند؛ در استخراج، تأخیر شبکه مستقیماً به حاشیهٔ سود مربوط میشود. شبکهٔ رله شبکهای است که تأخیر انتقال بلاک بین ماینرها را کم میکند.
- Bitcoin Relay Network اصلی: ۲۰۱۵، توسط Matt Corallo (توسعهدهندهٔ هسته)، چند گرهٔ تخصصی روی زیرساخت AWS در سراسر جهان که بیشتر ماینرها و استخرها را وصل میکرد.
- FIBRE (Fast Internet Bitcoin Relay Engine): جایگزین آن در ۲۰۱۶، ساختهٔ همان فرد؛ شبکهٔ رلهٔ مبتنی بر UDP که بهینهسازی compact block را برای کاهش داده و تأخیر پیاده میکند.
- Falcon: پیشنهادی هنوز در مرحلهٔ طرح، برگرفته از پژوهش دانشگاه Cornell؛ بهجای «ذخیره و ارسال» (store-and-forward) از cut-through routing استفاده میکند، یعنی بخشهای بلاک را به محض رسیدن پخش میکند و منتظر کامل شدن بلاک نمیماند.
شبکههای رله جایگزین شبکهٔ P2P نیستند، بلکه شبکههای روکش (overlay) هستند که بین گرههای با نیاز ویژه اتصال اضافه ایجاد میکنند؛ مثل بزرگراه که جای جادههای روستایی را نمیگیرد و فقط میانبر بین دو نقطهٔ پرترافیک است و برای رسیدن به بزرگراه هنوز به جادههای کوچک نیاز دارید.
کشف شبکه (Network Discovery)
گرهٔ تازهراهافتاده باید دستکم یک گرهٔ موجود را پیدا کند و به آن وصل شود. موقعیت جغرافیایی اهمیتی ندارد (توپولوژی شبکه جغرافیایی نیست)، پس هر گرهٔ موجود را میشود تصادفی انتخاب کرد.
اتصال و دستدهی (handshake)
اتصال از طریق TCP معمولاً روی پورت ۸۳۳۳ (یا پورت دیگری در صورت اعلام) انجام میشود. پس از اتصال، گره دستدهی را با ارسال پیام version شروع میکند؛ این پیام همیشه اولین پیامی است که هر همتا به همتای دیگر میفرستد. فیلدهای آن:
| فیلد | معنا |
|---|---|
nVersion |
نسخهٔ پروتکل P2P بیتکوین که کلاینت میفهمد (مثلاً 70002) |
nLocalServices |
فهرست خدمات محلی پشتیبانیشده (در آن زمان فقط NODE_NETWORK) |
nTime |
زمان جاری |
addrYou |
آدرس IP گرهٔ مقابل، آنگونه که از دید این گره دیده میشود |
addrMe |
آدرس IP گرهٔ محلی که خودش کشف کرده |
subver |
زیرنسخه، نوع نرمافزار (مثلاً /Satoshi:0.9.2.1/) |
BestHeight |
ارتفاع بلاکچین این گره |
گرهٔ دریافتکننده nVersion طرف مقابل را بررسی میکند و اگر سازگار باشد، پیام را با verack تأیید و اتصال را برقرار میکند.
یافتن همتاها
- DNS seeds: سرورهای DNS که فهرستی از IP گرههای بیتکوین میدهند. بعضی فهرست ثابتی از گرههای شنوای پایدار دارند و بعضی پیادهسازی سفارشی BIND هستند که زیرمجموعهای تصادفی از آدرسهای جمعآوریشده توسط crawler یا گرههای همیشهروشن را برمیگردانند. Bitcoin Core نام پنج DNS seed را در خود دارد؛ تنوع مالکیت و پیادهسازی، قابلیت اطمینان بالایی برای راهاندازی اولیه میدهد. گزینهٔ
-dnsseed(پیشفرض ۱) کنترل میکند که از آنها استفاده شود یا نه. - آدرس دستی: گرهٔ ناآگاه میتواند با آرگومان
-seednodeبه یک گره وصل شود فقط برای معرفی؛ پس از دریافت معرفیها، از آن قطع و به همتاهای جدید وصل میشود.
پیامهای addr و getaddr
پس از اتصال، گره پیام addr شامل آدرس خود را به همسایگان میفرستد؛ آنها به همسایگان خود میفرستند تا گره تازه شناختهشده و پیوند خوردهتر شود. گره همچنین میتواند getaddr بفرستد و فهرستی از آدرس همتاهای دیگر بگیرد. به این ترتیب هم همتا پیدا میکند و هم حضور خود را اعلام میکند.
مدیریت اتصالها
- مسیرها پایدار نیستند (گرهها میآیند و میروند)، پس گره باید با از دست دادن اتصالها همتاهای جدید کشف کند و به گرههای دیگر در راهاندازی کمک کند.
- برای بوتاسترپ فقط یک اتصال کافی است؛ اتصال به بیش از «چند» گره بیفایده و هدررفتن منابع است، اما باید به چند همتای مختلف وصل بود تا مسیرهای متنوع به شبکه وجود داشته باشد.
- پس از بوتاسترپ، گره آخرین اتصالهای موفق را به خاطر میسپارد تا در راهاندازی مجدد سریع به همتاهای قبلی برگردد؛ اگر هیچکدام پاسخ ندادند، دوباره از seed استفاده میشود.
- دستور
bitcoin-cli getpeerinfoفهرست اتصالها را با فیلدهایی مثلaddr،services،lastsend/lastrecv،bytessent/bytesrecv،conntime،pingtime،version،subver،inbound،startingheight،banscoreوsyncnodeنشان میدهد. - گزینهٔ
-connect=<IPAddress>مدیریت خودکار همتاها را خاموش میکند و گره فقط به IPهای مشخصشده وصل میشود. - اگر ۹۰ دقیقه هیچ ارتباطی روی اتصال نباشد، گره آن را قطعشده فرض میکند و همتای جدید میجوید. به این ترتیب شبکه بدون هیچ کنترل مرکزی خودش را با گرههای گذرا و مشکلات شبکه تطبیق میدهد و ارگانیک رشد و کوچک میشود.
گرههای کامل (Full Nodes)
گره کامل، بلاکچین کامل با همهٔ تراکنشها را نگه میدارد (دقیقتر: «گره کامل بلاکچین»). در سالهای نخست همهٔ گرهها کامل بودند؛ Bitcoin Core امروز هم گره کامل است و در دو سال اخیر کلاینتهای سبک پدید آمدهاند.
- گره کامل از بلاک پیدایش (genesis) شروع میکند و تا آخرین بلاک شبکه خودش همهچیز را میسازد و راستیآزمایی میکند؛ برای تأیید هر تراکنش به هیچ گره یا منبع دیگری تکیه نمیکند. فقط برای دریافت بلاکهای تازه به شبکه وابسته است.
- اجرای گره کامل «تجربهٔ خالص بیتکوین» است: راستیآزمایی مستقل همهچیز بدون اعتماد به سامانهٔ دیگر. نشانهاش: بیش از ۲۰ گیگابایت فضای ذخیرهسازی و دو تا سه روز همگامسازی؛ بهای استقلال کامل از مرجع مرکزی.
- پیادهسازیهای مختلفی با زبانها و معماریهای گوناگون هست، اما رایجترین Bitcoin Core (کلاینت مرجع، «کلاینت Satoshi») است و بیش از ۷۵٪ گرهها نسخههایی از آن را اجرا میکنند؛ در
subverبه شکل/Satoshi:0.8.6/دیده میشود.
تبادل «موجودی» (Inventory) و همگامسازی بلاکچین
گره نو فقط بلاک پیدایش را میشناسد (در نرمافزار ثابت و درونساخت است) و باید صدها هزار بلاک را از بلاک #0 دانلود کند. فرایند:
- پیام
versionشاملBestHeightاست؛ گره با آن میفهمد همتاها چند بلاک دارند و با زنجیر خودش مقایسه میکند. - همتاها پیام getblocks را با هش بالاترین بلاک محلی خود رد و بدل میکنند. همتایی که زنجیر بلندتری دارد میفهمد هش دریافتی مربوط به بلاکی قدیمیتر از نوک است، پس میداند طرف مقابل عقب است.
- همتای بلندتر، ۵۰۰ بلاک اول لازم را شناسایی و هشهایشان را با پیام inv (inventory) میفرستد.
- گرهٔ عقبمانده با دنبالهای از پیامهای getdata بلاکهای کامل را (با هشهای inv) درخواست میکند.
نکات تکمیلی: گره درخواستها را بین همهٔ همتاهای متصل پخش میکند تا هیچکدام تحت فشار نباشند و تعداد بلاکهای «در راه» به ازای هر همتا را زیر سقف MAX_BLOCKS_IN_TRANSIT_PER_PEER نگه میدارد؛ پس درخواست جدید فقط با تکمیل قبلیها ارسال میشود و همتاها سرعت را کنترل میکنند. هر بلاک دریافتی به بلاکچین افزوده میشود (فصل ۹) و روند تا رسیدن به شبکه ادامه مییابد. همین فرایند هر وقت گره مدتی آفلاین بوده (چند دقیقه یا یک ماه) تکرار میشود: getblocks ← inv ← دانلود بلاکهای گمشده.
گرههای SPV (تأیید پرداخت سادهشده)
همه نمیتوانند بلاکچین کامل را ذخیره کنند؛ بسیاری از کلاینتها برای گوشی، تبلت یا سامانههای توکار با فضا و برق محدود طراحی شدهاند. روش SPV به آنها اجازه میدهد بدون بلاکچین کامل کار کنند (کلاینت سبک). با رشد پذیرش بیتکوین، گرهٔ SPV رایجترین شکل گره، بهویژه برای کیف پولها، میشود.
- گره SPV فقط سرتیتر بلاکها (block headers) را دانلود میکند، نه تراکنشها. زنجیر حاصل ۱۰۰۰ برابر کوچکتر از بلاکچین کامل است.
- چون از همهٔ تراکنشها خبر ندارد، نمیتواند تصویر کاملی از UTXOهای خرجنشده بسازد. بهجای آن، از همتاها نمای جزئی و مورد نیاز را «در صورت تقاضا» میگیرد.
- تشبیه: گره کامل گردشگری با نقشهٔ دقیق همهٔ خیابانها و آدرسهاست؛ گره SPV گردشگری است که فقط یک خیابان اصلی را میشناسد و از رهگذران مسیر میپرسد. هر دو میتوانند وجود یک خیابان را با رفتن به آن تأیید کنند، اما گردشگر بدون نقشه نمیداند در خیابانهای فرعی چه خبر است، مثلاً نمیداند چند «خیابان کلیسا ۲۳» در شهر هست و این همان درست است یا نه؛ بهترین شانسش پرسیدن از افراد زیاد و امید به اینکه همه شان فریبکار نباشند.
اعتبارسنجی بر پایهٔ «عمق» بهجای «ارتفاع»
گره کامل زنجیری کاملاً راستیآزماییشده از هزاران بلاک و تراکنش تا بلاک پیدایش میسازد. گره SPV زنجیر بلاکها (نه همه تراکنشها) را بررسی و به تراکنش مورد نظر وصل میکند.
- مثال: تراکنشی در بلاک ۳۰۰٬۰۰۰. گره کامل ۳۰۰٬۰۰۰ بلاک را تا پیدایش پیوند میدهد و با پایگاه UTXO تأیید میکند که خروجی هنوز خرج نشده است. گره SPV نمیتواند خرجنشدگی UTXO را بررسی کند؛ پس با مسیر مرکل (merkle path) تراکنش را به بلاک حاوی آن وصل میکند، سپس صبر میکند تا شش بلاک ۳۰۰٬۰۰۱ تا ۳۰۰٬۰۰۶ روی آن انباشته شود و عمق را بررسی میکند. این که شبکه بلاک ۳۰۰٬۰۰۰ را پذیرفته و روی آن کار انجام داده، اثباتِ «نیابتی» برای دوبارهخرج نبودن تراکنش است.
- گره SPV را نمیتوان فریب داد که تراکنشی در بلاک است در حالی که نیست (با مسیر مرکل و اثبات کار زنجیر بلاکها بررسی میکند). اما میتوان وجود تراکنشی را از او پنهان کرد؛ چون همهٔ تراکنشها را ندارد، نمیتواند نبودِ تراکنشی مثل دوبارهخرج UTXO را بررسی کند. این ضعف برای حملهٔ انکار خدمت (DoS) یا دوبارهخرج (double spending) علیه گرههای SPV قابل استفاده است.
- دفاع: اتصال تصادفی به چند گره تا احتمال تماس با دستکم یک گرهٔ صادق بالا برود. این الزام باعث میشود SPV در برابر حملهٔ تقسیم شبکه (network partitioning) و Sybil (اتصال به گرهها/شبکهٔ جعلی) آسیبپذیر باشد.
- جمعبندی: گرههای SPV خوبمتصل برای بیشتر کاربردها امن کافیاند (تعادل منابع، کاربردی بودن و امنیت)؛ اما برای امنیت بینقص چیزی بهتر از گره کامل نیست.
نکته: گره کامل با بررسی کل زنجیر هزاران بلاک زیر تراکنش از خرجنشدن UTXO مطمئن میشود؛ گره SPV فقط میبیند بلاک با چند بلاک روی آن چهقدر «عمیق دفن شده».
پیامهای همگامسازی SPV
بهجای getblocks از getheaders استفاده میکند؛ همتا تا ۲٬۰۰۰ سرتیتر را در یک پیام headers برمیگرداند. گره SPV همچنین روی اتصال یک فیلتر تنظیم میکند تا جریان بلاکها و تراکنشهای آینده را پالایش کند. تراکنشهای مورد نظر با getdata درخواست و با پیام tx پاسخ داده میشوند.
ریسک حریم خصوصی
گره SPV برای تأیید گزینشی باید تراکنشهای خاص را بخواهد و درخواستهای مشخص ممکن است ناخواسته آدرسهای کیف پول را فاش کند. ناظر شبکه میتواند تراکنشهای درخواستی را ردگیری و آدرسها را به کاربر نسبت دهد. برای کاهش این خطر، bloom filter اضافه شد.
فیلترهای بلوم (Bloom Filters)
فیلتر بلوم یک فیلتر جستوجوی احتمالاتی است: الگوی دلخواه را بیآنکه دقیق گفته شود توصیف میکند. SPVها با آن از همتاها تراکنشهای منطبق با الگو را میخواهند بدون افشای دقیق آدرسها، کلیدها یا تراکنشها.
تشبیه: گردشگر بهجای «خیابان کلیسا ۲۳» میپرسد «خیابانی در این محله هست که نامش به R-C-H ختم شود؟». میتواند دقیقتر («ختم به U-R-C-H») یا کلیتر («ختم به H») بپرسد. الگوی کلیتر: نتایج بیشتر (که بسیاری بیربطاند) و حریم خصوصی بهتر؛ الگوی دقیق: نتایج کمتر و حریم خصوصی کمتر. فیلتر بلوم را میتوان به سمت دقت یا حریم خصوصی تنظیم کرد.
سازوکار
- ساختار: آرایهای با طول متغیر N بیت (bit field) و تعداد متغیر M تابع هش. توابع هش همیشه خروجی بین ۱ تا N میدهند و قطعی (deterministic) تولید میشوند، پس هر گرهٔ پیادهساز فیلتر بلوم برای ورودی یکسان نتیجهٔ یکسان میگیرد. با انتخاب N و M دقت (و در نتیجه حریم خصوصی) تنظیم میشود.
- شکلهای کتاب با آرایهٔ ۱۶ بیتی و سه تابع هش مثال میزنند.
- مقداردهی اولیه: همهٔ بیتها صفر.
- افزودن الگو: الگو را با هر یک از M تابع هش میگذرانیم؛ هر خروجی یک بیت را در آرایه ۱ میکند. پس از همهٔ توابع، الگو بهشکل M بیت تغییریافته «ثبت» شده است. الگوی دوم نیز همینطور. اگر بیتی از قبل ۱ باشد، تغییری نمیکند.
- با افزودن الگوهای بیشتر، فیلتر اشباع میشود و دقتش کم میشود؛ به همین دلیل ساختار داده «احتمالاتی» است. دقت به نسبت تعداد الگوها به اندازهٔ آرایه (N) و تعداد توابع (M) بستگی دارد: آرایهٔ بزرگتر و توابع بیشتر ← الگوهای بیشتر با دقت بیشتر.
- آزمون عضویت: الگو را هش میکنیم و بیتهای متناظر را بررسی میکنیم. اگر همه ۱ باشند، الگو «احتمالاً» ثبت شده («شاید، بله» — بهدلیل همپوشانی چند الگو قطعی نیست). اگر حتی یک بیت ۰ باشد، قطعاً ثبت نشده («قطعاً نه!») و این یک یقین است نه احتمال.
استفادهٔ SPV از فیلتر بلوم
- فیلتر «خالی» ساخته میشود (هیچ الگویی را منطبق نمیکند).
- فهرست آدرسها، کلیدها و هشهای مورد علاقه تهیه میشود: هش کلید عمومی، هش اسکریپت و شناسهٔ تراکنش از هر UTXO تحت کنترل کیف پول، و هر کدام به فیلتر افزوده میشود.
- SPV پیام filterload را با فیلتر برای همتا میفرستد.
- همتا هر تراکنش ورودی را بررسی میکند. بخشهای بررسیشده: شناسهٔ تراکنش (txid)، مؤلفههای داده در اسکریپتهای قفل هر خروجی (هر کلید و هش درون اسکریپت)، هر ورودی تراکنش و مؤلفههای داده امضای هر ورودی (یا witness script). بنابراین میتوان هش کلید عمومی، اسکریپت، مقادیر
OP_RETURN، کلید عمومی در امضا یا هر مؤلفهٔ آیندهٔ قراردادهای هوشمند را منطبق کرد. - تنها تراکنشهای منطبق ارسال میشود. در پاسخ به
getdata، همتا پیام merkleblock میفرستد که فقط سرتیتر بلاکهای منطبق و یک مسیر مرکل برای هر تراکنش منطبق دارد، سپس پیامهای tx حاوی تراکنشهای منطبق. - SPV مثبتهای کاذب (false positive) را دور میریزد و با تراکنشهای درست، مجموعهٔ UTXO و موجودی کیف پول را بهروز میکند؛ همزمان فیلتر را برای تراکنشهای آینده که به UTXO تازه ارجاع میدهند بهروز میکند و چرخه تکرار میشود.
مدیریت فیلتر: filteradd برای افزودن تعاملی الگو و filterclear برای پاکسازی. چون حذف الگو از فیلتر بلوم ممکن نیست، برای حذف باید فیلتر را پاک و فیلتر تازه بفرستید. پروتکل شبکه و سازوکار bloom برای SPV در BIP-37 (Peer Services) تعریف شده است.
SPV و حریم خصوصی
گره کامل همهٔ تراکنشها را میگیرد و هیچ اطلاعی دربارهٔ آدرسهای کیف پول فاش نمیکند؛ گره SPV فهرست فیلترشدهٔ مربوط به آدرسهای کیف پول را میگیرد، پس حریم خصوصی مالک کمتر است. بدون bloom، SPV باید آدرسها را صریحاً فهرست میکرد (نقض جدی حریم خصوصی). اما حتی با bloom هم مهاجمی که ترافیک SPV را رصد میکند یا مستقیماً به آن وصل است میتواند در طول زمان اطلاعات کافی برای کشف آدرسها جمع کند.
اتصالهای رمزنگاریشده و احرازهویتشده
بسیاری از کاربران تازهکار فرض میکنند ارتباطات گره بیتکوین رمز شده است؛ در حالی که پیادهسازی اصلی کاملاً بدون رمزنگاری (در clear) ارتباط میگیرد. برای گره کامل مشکل بزرگی نیست ولی برای SPV بزرگ است. دو راهحل:
انتقال از طریق Tor
Tor (The Onion Routing) نرمافزار و شبکهای است که با مسیرهای تصادفی، رمزنگاری و کپسولهسازی داده، ناشناسی، ردیابیناپذیری و حریم خصوصی میدهد.
- Bitcoin Core چند گزینهٔ پیکربندی برای انتقال ترافیک روی Tor دارد و میتواند hidden service (سرویس پنهان Tor) ارائه کند تا گرههای Tor مستقیماً روی Tor به گره شما وصل شوند.
- از نسخهٔ ۰٫۱۲ گره خودکار hidden service ارائه میدهد، اگر بتواند به سرویس Tor محلی وصل شود و کاربر پردازش به کوکی احرازهویت Tor دسترسی داشته باشد.
- دیباگ:
bitcoind --daemon --debug=tor؛ در لاگ باید پیامtor: ADD_ONION successfulرا ببینید. راهنمای بیشتر درdocs/tor.md.
احرازهویت و رمزنگاری P2P (BIP-150/151)
- BIP-151: رمزنگاری توافقی همهٔ ارتباطات بین دو گرهٔ پشتیبان.
- BIP-150: احرازهویت اختیاری همتا: گرهها هویت یکدیگر را با ECDSA و کلیدهای خصوصی احراز میکنند؛ مستلزم برقراری رمزنگاری BIP-151 قبل از احراز.
- تا ژانویهٔ ۲۰۱۷ در Bitcoin Core پیاده نشده بود، اما دستکم کلاینت جایگزین bcoin آنها را پیاده کرده بود.
- کاربردها: اتصال کلاینت SPV به یک گره کامل مورد اعتماد با حفاظت حریم خصوصی؛ ساخت شبکههای گرههای مورد اعتماد و جلوگیری از حملهٔ مرد میانی (MITM)؛ و در صورت فراگیری، افزایش مقاومت بیتکوین در برابر تحلیل ترافیک و نظارت، بهویژه در کشورهای استبدادی با اینترنت کنترلشده.
مخزنهای تراکنش (Transaction Pools)
تقریباً هر گره یک فهرست موقت از تراکنشهای تأییدنشده دارد: مخزن تراکنشهای تأییدنشده (mempool) یا transaction pool. گرهها با آن تراکنشهای شناختهشدهای را که هنوز در بلاکچین نیستند دنبال میکنند؛ مثلاً کیف پول پرداختهای ورودی دیدهشده و تأییدنشده را رصد میکند. تراکنشهای دریافتی پس از اعتبارسنجی به مخزن افزوده و به همسایگان رله میشوند.
مخزن یتیم (Orphan Pool)
بعضی پیادهسازیها مخزن جدایی برای تراکنشهای یتیم (orphan) دارند: تراکنشی که ورودیاش به تراکنشی هنوز ناشناخته (والد گمشده) ارجاع میدهد، موقتاً در مخزن یتیم میماند تا والد برسد. با افزودن تراکنش به مخزن اصلی، مخزن یتیم برای یتیمهایی که به خروجیهای آن (فرزندان) ارجاع میدهند بررسی میشود؛ معتبرها از یتیم خارج و به مخزن اصلی اضافه میشوند و فرایند بازگشتی برای نوادگان تکرار میشود. پس رسیدن والد، یک بازسازی آبشاری از کل زنجیرهٔ تراکنشهای وابسته را به راه میاندازد.
نکته: هر دو مخزن در حافظهٔ محلی هستند و روی دیسک ذخیره نمیشوند؛ از پیامهای شبکه پر میشوند و در شروع گره خالیاند.
مخزن UTXO
بعضی کلاینتها یک پایگاهدادهٔ UTXO (UTXO pool) هم دارند: مجموعهٔ همهٔ خروجیهای خرجنشدهٔ بلاکچین. اگرچه نامش شبیه مخزن تراکنش است، دادهای متفاوت است:
| ویژگی | مخزن تراکنش / یتیم | مخزن UTXO |
|---|---|---|
| مقدار اولیه | خالی | میلیونها ورودی (از بلاک پیدایش تا امروز) |
| محتوا | فقط تراکنشهای تأییدنشده | فقط خروجیهای تأییدشده |
| دیدگاه | محلی؛ بین گرهها بسیار متفاوت (بسته به زمان راهاندازی) | اجماع برآمده از شبکه؛ بین گرهها تقریباً یکسان |
| محل نگهداری | فقط حافظه | حافظه یا جدول ایندکسشده روی دیسک |
جمعبندی
- بیتکوین یک شبکهٔ P2P تخت و بدون مرجع مرکزی است؛ عدم تمرکز کنترل، اصل طراحی و مستلزم همین معماری است. «شبکهٔ گسترشیافته» پروتکلهای دیگر (Stratum، استخرها، کلاینتهای سبک) را از طریق دروازهها شامل میشود.
- هر گره ترکیبی از چهار عملکرد مسیریابی، پایگاهدادهٔ بلاکچین، استخراج و کیف پول است؛ گره کامل مستقل و معتبر راستیآزمایی میکند، اما گره SPV فقط سرتیتر بلاکها را نگه میدارد و با مسیر مرکل و عمق بلاک اعتبار را تخمین میزند.
- شبکههای رله (Relay Network، FIBRE، Falcon) تأخیر انتشار بلاک بین ماینرها را کم میکنند و روکشی بر شبکهٔ P2Pاند.
- کشف شبکه با TCP پورت ۸۳۳۳، پیامهای
version/verack، DNS seed،addr/getaddrو قطع اتصال بعد از ۹۰ دقیقه بیفعالیتی انجام میشود؛ همگامسازی گره کامل باgetblocks/inv/getdata(۵۰۰ بلاک در هرinv) و همگامسازی SPV باgetheaders/headers(تا ۲۰۰۰ سرتیتر). - فیلترهای بلوم (BIP-37) حریم خصوصی نسبی برای SPV میدهند (پیامهای
filterload،filteradd،filterclear،merkleblock) اما مصون از تحلیل بلندمدت نیستند. مثبت کاذب ممکن است، اما منفی کاذب هرگز. - ارتباط پیشفرض بیتکوین رمز نشده است؛ Tor و پیشنهادهای BIP-150/151 برای رمزنگاری و احرازهویت ارائه شدهاند.
- گرهها سه نوع مخزن دارند: mempool و مخزن یتیم (محلی و موقت و فقط در حافظه) و UTXO pool (مجموعهٔ اجماعی خروجیهای خرجنشده).
فصل ۹ — بلاکچین (The Blockchain)
مقدمه
بلاکچین یک ساختار دادهٔ مرتب و «پسپیوندی» از بلاکهای تراکنش است. میتوان آن را در یک فایل ساده یا یک پایگاهداده ذخیره کرد؛ Bitcoin Core فرادادههای بلاکچین را در پایگاهدادهٔ LevelDB گوگل نگه میدارد. هر بلاک به بلاک قبلی خود «پساشاره» میکند. بلاکچین را معمولاً مثل پشتهای عمودی تصویر میکنند که اولین بلاک بنیان آن است؛ از همین رو اصطلاحهایی مانند ارتفاع (height) برای فاصله از بلاک اول و بالا/نوک (top/tip) برای تازهترین بلاک به کار میرود.
- هر بلاک با یک هش شناسایی میشود که با الگوریتم SHA256 روی سرتیتر بلاک تولید میشود.
- هر بلاک از طریق فیلد «هش بلاک قبلی» (previous block hash) در سرتیتر به بلاک والد ارجاع میدهد؛ یعنی هش والد درون سرتیتر فرزند قرار دارد. این زنجیرهٔ هشها تا اولین بلاک تاریخ، یعنی بلاک پیدایش (genesis block)، ادامه دارد.
- یک بلاک فقط یک والد دارد (چون تنها یک فیلد «هش بلاک قبلی» دارد) ولی ممکن است موقتاً چند فرزند داشته باشد؛ مثلاً هنگام یک فورک (انشعاب موقت) که دو ماینر تقریباً همزمان بلاک پیدا کنند. سرانجام فقط یک فرزند در زنجیر میماند و انشعاب حل میشود.
اثر آبشاری و تغییرناپذیری
چون فیلد «هش بلاک قبلی» داخل سرتیتر است، بر هش خود بلاک تأثیر میگذارد. اگر والد به هر شکلی تغییر کند، هشش عوض میشود؛ این اشارهگر فرزند را عوض میکند، که هش فرزند را عوض میکند، که نوه را عوض میکند و همینطور تا نوک زنجیر. پس وقتی نسلهای بسیاری بعد از یک بلاک آمدهاند، تغییر آن بلاک مستلزم بازمحاسبهٔ همهٔ بلاکهای بعدی است که انرژی و محاسبهٔ عظیمی میخواهد. همین موجب تغییرناپذیری تاریخ عمیق بلاکچین میشود، که ویژگی کلیدی امنیت بیتکوین است.
تشبیه زمینشناسی: لایههای سطحی ممکن است با فصلها عوض شوند یا بر باد روند، اما چند اینچ پایینتر لایهها پایدار و در عمق صدها فوت، تصویری دستنخورده از میلیونها سال پیشاند.
- چند بلاک آخر ممکن است در اثر بازمحاسبهٔ زنجیر (بهعلت فورک) بازبینی شوند؛ شش بلاک بالایی مثل چند اینچ خاک سطحیاند.
- پس از ۱۰۰ بلاک پایداری آنقدر زیاد است که تراکنش کوینبیس (coinbase) (تراکنش حاوی بیتکوین تازهاستخراجشده) قابل خرج میشود.
- پس از چند هزار بلاک (حدود یک ماه) بلاکچین عملاً تاریخ تثبیتشده است.
- پروتکل همیشه اجازه میدهد زنجیری بلندتر زنجیر فعلی را لغو کند و احتمال برگشت هر بلاک همیشه هست، اما با گذر زمان این احتمال بینهایت کوچک میشود.
ساختار یک بلاک
بلاک ساختار دادهٔ ظرفی است که تراکنشها را برای ثبت در دفتر کل عمومی گرد هم میآورد: یک سرتیتر (فراداده) و سپس فهرست بلندی از تراکنشها که بیشتر حجم را میسازند. سرتیتر ۸۰ بایت است، در حالی که تراکنش متوسط دستکم ۲۵۰ بایت و متوسط تعداد تراکنشهای بلاک بیش از ۵۰۰ است؛ پس بلاک کامل حدود ۱۰۰۰ برابر سرتیتر است.
| اندازه | فیلد | توضیح |
|---|---|---|
| ۴ بایت | Block Size | اندازهٔ بلاک (بر حسب بایت) پس از این فیلد |
| ۸۰ بایت | Block Header | چند فیلد که سرتیتر را میسازند |
| ۱ تا ۹ بایت (VarInt) | Transaction Counter | تعداد تراکنشهای بعدی |
| متغیر | Transactions | تراکنشهای ثبتشده در این بلاک |
سرتیتر بلاک (Block Header)
سرتیتر سه مجموعه فراداده دارد: (۱) ارجاع به هش بلاک قبلی که بلاک را به زنجیر وصل میکند؛ (۲) درجهٔ دشواری، مهر زمانی و nonce که به رقابت استخراج (فصل ۱۰) مربوطاند؛ (۳) ریشهٔ درخت مرکل که خلاصهٔ کارآمد همهٔ تراکنشهای بلاک است.
| اندازه | فیلد | توضیح |
|---|---|---|
| ۴ بایت | Version | شمارهٔ نسخه برای ردیابی ارتقای نرمافزار/پروتکل |
| ۳۲ بایت | Previous Block Hash | هش بلاک قبلی (والد) در زنجیر |
| ۳۲ بایت | Merkle Root | هش ریشهٔ درخت مرکل تراکنشهای این بلاک |
| ۴ بایت | Timestamp | زمان تقریبی ساخت بلاک (ثانیه از Unix Epoch) |
| ۴ بایت | Difficulty Target | هدف دشواری الگوریتم اثبات کار برای این بلاک |
| ۴ بایت | Nonce | شمارندهای برای الگوریتم اثبات کار |
(جمع: ۴+۳۲+۳۲+۴+۴+۴ = ۸۰ بایت.)
شناسههای بلاک: هش سرتیتر و ارتفاع بلاک
هش بلاک
شناسهٔ اصلی بلاک اثر انگشت رمزنگاری آن است که با دو بار هش کردن سرتیتر با SHA256 (double-SHA256) بهدست میآید. حاصل ۳۲ بایتی را «هش بلاک» میگویند، ولی دقیقتر «هش سرتیتر بلاک» است چون فقط سرتیتر در محاسبه میآید. مثال: هش اولین بلاک تاریخ بیتکوین:
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
هش بلاک آن را یکتا و بیابهام تعیین میکند و هر گره میتواند مستقلاً با هش سرتیتر آن را محاسبه کند. نکته: هش بلاک داخل ساختار داده بلاک نیست، نه هنگام انتقال در شبکه و نه هنگام ذخیره؛ هر گره آن را هنگام دریافت بلاک حساب میکند (ممکن است در جدول جداگانهای بهعنوان فراداده برای ایندکس و بازیابی سریعتر ذخیره شود).
ارتفاع بلاک (Block Height)
راه دوم شناسایی: جایگاه بلاک در بلاکچین. اولین بلاک در ارتفاع ۰ است. هر بلاک بعدی یک جایگاه بالاتر است. ارتفاع بلاک در اول ژانویهٔ ۲۰۱۷ حدود ۴۴۶٬۰۰۰ بود، یعنی ۴۴۶٬۰۰۰ بلاک روی بلاک اول (ژانویهٔ ۲۰۰۹).
- برخلاف هش، ارتفاع شناسهٔ یکتا نیست: یک بلاک همیشه ارتفاع مشخص و ثابتی دارد، اما یک ارتفاع لزوماً یک بلاک را مشخص نمیکند؛ دو یا چند بلاک ممکن است برای یک جایگاه رقابت کنند (بخش «فورکهای بلاکچین» در فصل ۱۰).
- ارتفاع هم جزو ساختار داده بلاک نیست؛ هر گره هنگام دریافت بلاک آن را پویا حساب میکند و ممکن است برای بازیابی سریعتر در جدول ایندکس ذخیره کند.
خلاصه: هش بلاک همیشه یک بلاک را یکتا مشخص میکند و هر بلاک ارتفاعی معین دارد، ولی یک ارتفاع میتواند چند بلاک رقیب داشته باشد.
بلاک پیدایش (Genesis Block)
اولین بلاک زنجیر در ۲۰۰۹ ساخته شد و جد مشترک همهٔ بلاکهاست: از هر بلاکی به عقب بروید سرانجام به آن میرسید. چون بلاک پیدایش بهصورت ثابت در نرمافزار کلاینت کدگذاری شده (در Bitcoin Core فایل chainparams.cpp) و قابل تغییر نیست، هر گره همیشه با دستکم یک بلاک شروع میکند و هش، ساختار، زمان ساخت و حتی تنها تراکنش آن را میشناسد؛ همان «ریشهٔ امن» برای ساختن زنجیر قابل اعتماد.
- هش بلاک پیدایش:
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f— در هر کاوشگر بلاک (مثل blockchain.info) جستوجوپذیر است. - با
bitcoin-cli getblock <hash>میتوان آن را دید. فیلدهای نمونه:size=۲۸۵،height=۰،version=۱،merkleroot=4a5e1e4b…a33b(برابر با تنها تراکنش بلاک)،time=۱۲۳۱۰۰۶۵۰۵،nonce=۲۰۸۳۲۳۶۸۹۳،bits=1d00ffff،difficulty=۱، وnextblockhash=00000000839a8e68…6048. - پیام پنهان: ورودی تراکنش کوینبیس بلاک پیدایش متنی از روزنامهٔ The Times مورخ ۳ ژانویهٔ ۲۰۰۹ دربارهٔ آستانهٔ دومین کمک مالی دولت به بانکها (second bailout) دارد. این پیام هم اثباتی برای کمترین تاریخ ممکن ساخت بلاک بود و هم یادآوری طعنهآمیز اهمیت نظام پولی مستقل، در دوران بحران مالی بیسابقهٔ جهانی. آن را Satoshi Nakamoto درج کرد.
پیوند دادن بلاکها در بلاکچین
گرههای کامل نسخهٔ محلی بلاکچین را از بلاک پیدایش نگه میدارند و با یافتن بلاکهای جدید آن را گسترش میدهند. گره هر بلاک ورودی را اعتبارسنجی و سپس به زنجیر موجود پیوند میزند؛ برای این کار فیلد «previous block hash» سرتیتر را بررسی میکند.
مثال کتاب: گرهی ۲۷۷٬۳۱۴ بلاک دارد و هش سرتیتر آخرین بلاک 00000000000000027e7ba6fe…1632249 است. بلاک جدیدی با size=۴۳٬۵۶۰، version=۲ و previousblockhash برابر همان هش میرسد (بهعلاوهٔ merkleroot، time، difficulty، nonce و فهرست tx). چون هش والد را میشناسد و آخرین بلاک در ارتفاع ۲۷۷٬۳۱۴ است، بلاک جدید فرزند آخرین بلاک است و زنجیر را به ارتفاع ۲۷۷٬۳۱۵ گسترش میدهد.
درختهای مرکل (Merkle Trees)
هر بلاک خلاصهای از همهٔ تراکنشهایش را با درخت مرکل (درخت هش دودویی، binary hash tree) دارد؛ ساختاری برای خلاصهسازی و راستیآزمایی یکپارچگی مجموعههای بزرگ داده. درخت مرکل دودویی است و گرههایش هشهای رمزنگاریاند. (درختها معمولاً وارونه رسم میشوند: ریشه بالا، برگها پایین.)
- درخت با هش کردن بازگشتی جفتها ساخته میشود تا تنها یک هش بماند: ریشهٔ مرکل (merkle root). تابع هش درخت: double-SHA256.
- برای N عنصر، بررسی عضویت یک عنصر حداکثر 2·log₂(N) محاسبه میخواهد؛ بسیار کارآمد.
ساخت از پایین به بالا
با چهار تراکنش A تا D که برگها هستند (خود تراکنشها در درخت ذخیره نمیشوند، فقط هششان):
HA = SHA256(SHA256(Transaction A))و به همین ترتیب HB، HC، HD.- هر دو برگ متوالی در یک گره والد خلاصه میشوند: دو هش ۳۲ بایتی الحاق (concatenate) میشوند و رشتهٔ ۶۴ بایتی دوباره هش میشود:
HAB = SHA256(SHA256(HA + HB)). - روند تا رسیدن به یک گره (ریشه) ادامه دارد. این هش ۳۲ بایتی در سرتیتر بلاک ذخیره میشود و همهٔ دادههای تراکنشها را خلاصه میکند.
چون درخت دودویی است باید تعداد برگها زوج باشد؛ اگر تعداد تراکنشها فرد باشد هش آخرین تراکنش تکرار (duplicate) میشود تا درخت متوازن شود (مثلاً تراکنش C دوبار).
همین روش برای هر اندازهٔ درخت تعمیم مییابد: بلاکها معمولاً چند صد تا بیش از هزار تراکنش دارند اما ریشه همیشه فقط ۳۲ بایت است — چه یک تراکنش باشد چه صدهزار.
مسیر مرکل (Merkle Path)
برای اثبات وجود یک تراکنش در بلاک، گره فقط باید log₂(N) هش ۳۲ بایتی تولید کند: مسیر احراز یا مسیر مرکل از تراکنش تا ریشه. چون لگاریتم دودویی کند رشد میکند، مسیر ۱۰ تا ۱۲ هشی (۳۲۰ تا ۳۸۴ بایت) برای اثبات یک تراکنش از میان بیش از هزار تراکنش یک بلاک یکمگابایتی کافی است.
مثال شکل ۹-۵: برای اثبات حضور تراکنش K (هش HK) در درخت ۱۶ برگی، گره چهار هش (جمعاً ۱۲۸ بایت) ارائه میدهد: HL، HIJ، HMNOP، HABCDEFGH. هر گره دیگر با چهار هش جفتی بیشتر — HKL، HIJKL، HIJKLMNOP و ریشهٔ مرکل — میتواند بررسی کند HK در ریشه هست.
کد نمونه (فقط ایده)
مثال ۹-۱ (C++ با کتابخانهٔ libbitcoin) تابع create_merkle را نشان میدهد: تا وقتی بیش از یک هش در فهرست هست حلقه میزند؛ اگر تعداد فرد باشد آخری را تکرار میکند؛ هر جفت را الحاق و با bitcoin_hash (دو بار SHA256) هش و در فهرست جدید میگذارد. در مثال ۹-۲ با سه هش ورودی (…00، …11، …22) خروجی ریشه d47780c0…4ba3 شد.
کارایی درخت مرکل
| تعداد تراکنش | اندازهٔ تقریبی بلاک | اندازهٔ مسیر (هش) | اندازهٔ مسیر (بایت) |
|---|---|---|---|
| ۱۶ | ۴ کیلوبایت | ۴ | ۱۲۸ |
| ۵۱۲ | ۱۲۸ کیلوبایت | ۹ | ۲۸۸ |
| ۲۰۴۸ | ۵۱۲ کیلوبایت | ۱۱ | ۳۵۲ |
| ۶۵٬۵۳۵ | ۱۶ مگابایت | ۱۶ | ۵۱۲ |
اندازهٔ بلاک بهسرعت رشد میکند (۴ کیلوبایت تا ۱۶ مگابایت) ولی مسیر مرکل خیلی کندتر (۱۲۸ تا ۵۱۲ بایت). بنابراین گره میتواند فقط سرتیتر بلاکها (۸۰ بایت برای هر بلاک) را دانلود و با گرفتن مسیر کوچکی از گره کامل، حضور تراکنش در بلاک را راستیآزمایی کند — بدون ذخیرهٔ بیشتر بلاکچین که ممکن است چند گیگابایت باشد.
درخت مرکل و SPV
گرههای SPV همهٔ تراکنشها را ندارند و بلاک کامل دانلود نمیکنند؛ برای تأیید حضور تراکنش در بلاک از مسیر مرکل بهره میبرند. مثلاً SPV علاقهمند به پرداختهای ورودی به یک آدرس کیف پول، فیلتر بلوم (فصل ۸) را روی اتصالهایش میگذارد. وقتی همتا تراکنشی منطبق ببیند، بلاک را با پیام merkleblock میفرستد که شامل سرتیتر بلاک و مسیر مرکل از تراکنش مورد نظر تا ریشهٔ مرکل بلاک است. SPV از مسیر برای پیوند تراکنش به بلاک و از سرتیتر برای پیوند بلاک به بلاکچین استفاده میکند؛ ترکیب این دو پیوند اثبات میکند تراکنش در بلاکچین ثبت شده است. در مجموع SPV کمتر از یک کیلوبایت داده (سرتیتر + مسیر) میگیرد، بیش از هزار برابر کمتر از بلاک کامل (آن زمان حدود ۱ مگابایت).
بلاکچینهای آزمایشی بیتکوین
بیش از یک بلاکچین بیتکوین وجود دارد. بلاکچین «اصلی» که Satoshi Nakamoto در ۳ ژانویهٔ ۲۰۰۹ ساخت و بلاک پیدایش آن بررسی شد، mainnet نام دارد. بلاکچینهای آزمایشی: testnet، segnet و regtest.
Testnet
بلاکچین، شبکه و ارز آزمایشی با شبکهٔ P2P زندهٔ کامل: کیف پول، بیتکوین آزمایشی (testnet coins)، استخراج و همهٔ امکانات mainnet. فقط دو تفاوت: سکهها ارزش ندارند و دشواری استخراج بهقدری کم است که هرکس بهراحتی استخراج کند (تا بیارزش بمانند). هر نرمافزار مخصوص mainnet باید اول روی testnet آزموده شود تا هم توسعهدهندگان از زیانهای مالی ناشی از باگ و هم شبکه از رفتار ناخواسته محافظت شود.
- حفظ بیارزشی کار سادهای نیست: برخی با GPU و ASIC در testnet استخراج میکنند، دشواری را بالا میبرند، استخراج با CPU را ناممکن میکنند و سکهٔ آزمایشی را کمیاب و ارزشمند میکنند؛ پس گاهی testnet باید با بلاک پیدایش جدید دوباره راهاندازی شود تا دشواری ریست شود.
- نسخهٔ جاری testnet3 است (سومین نسخه، فوریهٔ ۲۰۱۱ برای ریست دشواری راهاندازی مجدد شد). اندازهٔ آن در اوایل ۲۰۱۷ بیش از ۲۰ گیگابایت بود و همگامسازی حدود یک روز میبرد؛ بهتر است روی ماشین مجازی (VirtualBox، Docker، سرور ابری) اجرا شود.
- اجرا:
bitcoind -testnet(دایرکتوری داده~/.bitcoin/testnet3)؛ برای ارتباط:bitcoin-cli -testnet getinfoوbitcoin-cli -testnet getblockchaininfo(فیلدهایی مانندchain: "test"،blocks،headers،verificationprogress،chainwork،pruned). - پیادهسازیهای دیگر مانند btcd (Go) و bcoin (JavaScript) نیز testnet3 را پشتیبانی میکنند. در اوایل ۲۰۱۷ testnet3 از سگویت (SegWit) هم پشتیبانی میکرد در حالی که روی mainnet هنوز فعال نشده بود.
Segnet
در ۲۰۱۶ testnet ویژهای برای توسعه و آزمون Segregated Witness (سگویت) راهاندازی شد. با افزودن سگویت به testnet3 دیگر لازم نیست. احتمالاً در آینده testnetهای ویژهٔ آزمودن یک ویژگی یا تغییر معماری بزرگ ساخته خواهند شد.
Regtest
مخفف Regression Testing؛ ویژگی Bitcoin Core برای ساخت بلاکچین محلی و بسته جهت آزمون. برخلاف testnet3 عمومی، هر بار از صفر با بلاک پیدایش محلی راه میافتد و میتوان فقط با یک گره یا چند گره آن را به کار گرفت.
- اجرا:
bitcoind -regtest(دایرکتوری~/.bitcoin/regtest) وbitcoin-cli -regtest getblockchaininfo(در ابتداblocks=۰). - با
bitcoin-cli -regtest generate 500در چند ثانیه ۵۰۰ بلاک استخراج میشود. موجودی کیف پول پس از آن فقط پاداش ۴۰۰ بلاک اول را نشان میدهد (۱۲٬۴۶۲٫۵ بیتکوین در مثال) چون پاداش کوینبیس باید ۱۰۰ بلاک عمق داشته باشد تا خرجشدنی شود.
استفاده از بلاکچینهای آزمایشی در توسعه
محیطهای regtest، segnet، testnet3 و mainnet طیفی از آزمایشگاهها را فراهم میکنند؛ چه برای توسعهٔ Bitcoin Core یا کلاینت اجماع دیگر، چه برنامهای مثل کیف پول، صرافی، فروشگاه آنلاین یا حتی قراردادهای هوشمند و اسکریپتهای پیچیده. خط لولهٔ پیشنهادی: نخست روی regtest محلی در حین توسعه آزمایش کنید؛ هنگام آمادگی برای شبکهٔ عمومی به testnet بروید (محیط پویاتر با تنوع بیشتر کد و برنامه)؛ و وقتی از درستی کار مطمئن شدید روی mainnet مستقر کنید. با هر تغییر یا رفع باگ، این چرخه را از اول تکرار کنید: ابتدا regtest، سپس testnet، سپس تولید (production).
جمعبندی
- بلاکچین فهرست مرتب و پسپیوندی از بلاکهاست؛ هر بلاک با double-SHA256 سرتیتر ۸۰ بایتیاش شناسایی میشود و هش والد را درون خود دارد، پس تغییر هر بلاک قدیمی مستلزم بازمحاسبهٔ همهٔ بلاکهای بعدی است؛ این منشأ تغییرناپذیری (تثبیت پس از حدود ۶ بلاک و عملاً کامل پس از چند هزار بلاک) است.
- سرتیتر شامل Version، Previous Block Hash، Merkle Root، Timestamp، Difficulty Target و Nonce است؛ بلاک با ۴ بایت اندازه، سرتیتر، شمارندهٔ تراکنش (VarInt) و تراکنشها ساخته میشود.
- هش بلاک یکتاست و در بلاک ذخیره نمیشود؛ ارتفاع یکتا نیست (فورک میتواند چند بلاک همارتفاع بسازد) و آن هم ذخیره نمیشود.
- بلاک پیدایش (هش
000000000019d6…ce26f، ارتفاع ۰، با پیام روزنامهٔ Times) در کد کلاینت ثابت است و ریشهٔ اعتماد هر گره. - درخت مرکل با double-SHA256 همهٔ تراکنشهای بلاک را در ریشهٔ ۳۲ بایتی خلاصه میکند و مسیر مرکل با log₂(N) هش اثبات حضور یک تراکنش را ممکن میسازد؛ پایهٔ کار گرههای SPV (سرتیتر ۸۰ بایتی + مسیر کوچک).
- بلاکچینهای آزمایشی testnet3، segnet و regtest محیطهای ایمن توسعهاند؛ چرخهٔ پیشنهادی توسعه regtest ← testnet ← mainnet است.
فصل ۱۰ — استخراج و اجماع (Mining and Consensus)
مقدمه: ماینینگ واقعاً برای چیست؟
واژهٔ «استخراج» (mining) گمراهکننده است، چون ذهن را به سمت پاداش، یعنی بیتکوین تازهضربشده، میبرد. اما هدف اصلی ماینینگ تولید سکه نیست؛ پاداش تنها سازوکار انگیزشی است. ماینینگ همان چیزی است که امنیت بیتکوین را غیرمتمرکز میکند: تراکنشها را اعتبارسنجی و «تسویه» میکند و بدون هیچ مرجع مرکزی به اجماع سراسری میرسد. به بیان کتاب، اگر ماینینگ را فقط فرایند ساخت سکه بدانیم، وسیله را با هدف اشتباه گرفتهایم.
نکات پایه:
- بهطور میانگین هر ۱۰ دقیقه یک بلاک استخراج میشود و تراکنشهای موجود در آن «تأییدشده» (confirmed) به شمار میآیند؛ گیرندهٔ بیتکوین میتواند آنها را خرج کند.
- ماینر دو نوع درآمد دارد: پاداش بلاک (سکهٔ جدید) و کارمزد تراکنشهای داخل بلاک.
- برای دریافت پاداش، ماینرها بر سر حل یک مسئلهٔ دشوار مبتنی بر هش رقابت میکنند. جواب این مسئله همان اثبات کار (Proof-of-Work) است که داخل بلاک قرار میگیرد و گواه صرف تلاش محاسباتی قابلتوجه است.
- نام «ماینینگ» از اینجاست که پاداش با روند نزولی (مانند استخراج فلزات گرانبها) کاهش مییابد و عرضهٔ پول از همین مسیر ایجاد میشود، مشابه چاپ اسکناس توسط بانک مرکزی.
- پاداش هر ۲۱۰٬۰۰۰ بلاک (حدود چهار سال) نصف میشود: ۵۰ بیتکوین در ژانویهٔ ۲۰۰۹، ۲۵ در نوامبر ۲۰۱۲، ۱۲٫۵ در ژوئیهٔ ۲۰۱۶. تا حدود سال ۲۱۴۰ همهٔ بیتکوینها (کمی کمتر از ۲۱ میلیون) منتشر شده و پس از آن ماینرها فقط از کارمزد درآمد خواهند داشت.
- در زمان نگارش کتاب سهم کارمزد کمتر از ۰٫۵٪ درآمد ماینر بود، اما انتظار میرود با کاهش پاداش و افزایش تراکنشها، سهم کارمزد رفتهرفته غالب شود.
در ادامهٔ فصل، ابتدا ماینینگ بهعنوان سازوکار عرضهٔ پول بررسی میشود و سپس مهمترین کارکردش یعنی اجماع غیرمتمرکز. خط روایی فصل، تراکنش آلیس (خرید قهوه از کافهٔ باب) است که توسط تجهیزات استخراج جینگ (Jing) در بلاک ۲۷۷٬۳۱۶ قرار میگیرد و سپس همان بلاک از طریق «اجماع نوپدید» توسط شبکه پذیرفته میشود.
اقتصاد بیتکوین و خلق پول
- بیتکوینها در هر بلاک با نرخ ثابتِ نزولی «ضرب» میشوند. هر ۲۱۰٬۰۰۰ بلاک نرخ انتشار ۵۰٪ کم میشود. نصفشدن بعدی (به ۶٫۲۵) در بلاک ۶۳۰٬۰۰۰ و در حدود سال ۲۰۲۰ انتظار میرفت.
- در مجموع ۳۲ بار نصفشدن رخ میدهد تا پاداش در بلاک ۶٬۷۲۰٬۰۰۰ (حدود سال ۲۱۳۷) به کمینهٔ واحد، یعنی ۱ ساتوشی، برسد. پس از حدود ۶٫۹۳ میلیون بلاک (حدود ۲۱۴۰) مجموع انتشار تقریباً ۲٬۰۹۹٬۹۹۹٬۹۹۷٬۶۹۰٬۰۰۰ ساتوشی است.
- اسکریپت پایتونی کتاب (
max_money) با حلقهای ساده همین را محاسبه میکند: پاداش اولیه (۵۰×۱۰⁸ ساتوشی) × ۲۱۰٬۰۰۰ بلاک، جمعشده در هر دوره و تقسیم بر ۲ در هر دور تا صفر شدن؛ خروجی ۲۰۹۹۹۹۹۹۹۷۶۹۰۰۰۰ ساتوشی است. - ماینر میتواند عمداً کمتر از پاداش کامل را بردارد؛ بنابراین سقف ۲۱ میلیون «حداکثر ممکن» است و ممکن است در عمل کمتر منتشر شود.
- عرضهٔ محدود و نزولی، پول را در برابر تورم (چاپ بیحد) ایمن میکند.
کادر: پول انقباضی (Deflationary)
پیامد مهم و پرمناقشهٔ عرضهٔ ثابت این است که ارز ذاتاً به انقباض (افزایش قدرت خرید در گذر زمان) گرایش دارد. بسیاری از اقتصاددانان انقباض را فاجعه میدانند، چون مردم بهجای خرجکردن پول را انبار میکنند (نمونه: «دههٔ گمشدهٔ» ژاپن که تقاضا فروپاشید و چرخهٔ انقباضی شکل گرفت). طرفداران بیتکوین پاسخ میدهند که انقباض فینفسه بد نیست؛ تنها نمونهٔ تاریخی ما با فروپاشی تقاضا همراه بوده، حال آنکه انقباض بیتکوین ناشی از عرضهٔ محدود و قابلپیشبینی است، نه سقوط تقاضا. در مقابل، تورم نوعی مالیات پنهان است که پساندازکنندگان را جریمه و بدهکاران (از جمله دولتها) را نجات میدهد. اینکه انقباض در غیاب رکود شدید مشکلساز است یا مزیت، هنوز مشخص نیست.
اجماع غیرمتمرکز
سنتیترین سامانههای پرداخت بر مرجع مرکزی (اتاق پایاپای) تکیه دارند. در بیتکوین هر گره کامل (full node) نسخهٔ مستقل خود از دفتر کل را از روی اطلاعاتی که از کانالهای ناامن میرسد میسازد و به همان نتیجهای میرسد که دیگران. نوآوری اصلی ساتوشی ناکاموتو اجماع نوپدید (emergent consensus) است: توافق صریح، رأیگیری یا لحظهٔ مشخصی ندارد؛ بلکه محصول تعامل ناهمگام هزاران گرهٔ مستقل است که قواعد سادهای را دنبال میکنند.
اجماع از چهار فرایند مستقل پدید میآید که روی گرههای مختلف اجرا میشود:
- اعتبارسنجی مستقل هر تراکنش توسط هر گرهٔ کامل بر پایهٔ فهرست جامعی از معیارها؛
- تجمیع مستقل تراکنشها در بلاکهای جدید توسط گرههای ماینر، همراه با اثبات محاسباتی (اثبات کار)؛
- اعتبارسنجی مستقل بلاکهای جدید توسط هر گره و سوارکردنشان در یک زنجیر؛
- انتخاب مستقل زنجیری که بیشترین مجموع کار (اثبات کار تجمعی) را دارد.
اعتبارسنجی مستقل تراکنشها
هر گرهٔ بیتکوین پیش از ارسال تراکنش به همسایگان آن را بررسی میکند؛ بنابراین تراکنش نامعتبر در اولین گره دور ریخته میشود. فهرست معیارها (در توابع AcceptToMemoryPool، CheckTransaction و CheckInputs در Bitcoin Core) شامل این موارد است:
- ساختار و نحو تراکنش درست باشد؛ فهرست ورودیها و خروجیها خالی نباشد؛
- اندازه کمتر از
MAX_BLOCK_SIZEو دستکم ۱۰۰ بایت باشد؛ - مقدار هر خروجی و مجموع آنها در بازهٔ مجاز (کمتر از ۲۱ میلیون و بیش از آستانهٔ «غبار» dust) باشد؛
- هیچ ورودی از نوع coinbase نباشد (تراکنش coinbase نباید رله شود)؛
- شرطهای
nLocktimeوnSequenceبرقرار باشد (بر اساس MedianTimePast)؛ - تعداد عملیات امضا (SIGOPS) از حد مجاز بیشتر نباشد؛
scriptSigفقط عدد/داده روی پشته بگذارد و اسکریپت قفل از قالبهای استاندارد (isStandard) باشد؛- هر خروجیِ ارجاعشده باید موجود و خرجنشده باشد و در استخر یا زنجیر اصلی یافت شود؛ اگر موجود نبود، تراکنش یتیم (orphan) است و به استخر یتیمها میرود؛ اگر پیشتر توسط تراکنش دیگری در استخر مصرف شده باشد، رد میشود؛
- خروجی coinbase فقط پس از ۱۰۰ تأیید (
COINBASE_MATURITY) قابل خرج است؛ - مجموع ورودیها نباید کمتر از مجموع خروجیها باشد و کارمزد نباید زیر
minRelayTxFeeباشد؛ - اسکریپتهای باز (unlocking) باید با اسکریپتهای قفل خروجیهای متناظر معتبر شوند.
این شروط در طول زمان تغییر میکنند (برای مقابله با حملات منع خدمت یا گاهی نرمکردن قواعد). حاصل این بررسی مستقل، استخر تراکنشهای معتبر اما تأییدنشدهٔ هر گره است: مخزن تراکنشهای تأییدنشده (mempool).
گرههای ماینر
برخی گرهها متخصصاند: ماینرها. جینگ، دانشجوی مهندسی کامپیوتر در شانگهای (که در فصل ۱ معرفی شد)، با «دستگاه استخراج» (mining rig) کار میکند که به یک سرور با گرهٔ کامل متصل است. (برخی ماینرها بدون گرهٔ کامل کار میکنند؛ بخش استخرها.) گرهٔ جینگ مثل همهٔ گرهها تراکنشها را دریافت و رله میکند، اما علاوه بر آن آنها را در یک بلاک تجمیع میکند.
رسیدن بلاک جدید از شبکه برای ماینر اهمیت ویژهای دارد: بلاک جدید یعنی رقابت دور قبل تمام شد و کس دیگری برنده شد؛ ولی همین بلاک «تپانچهٔ شروع» رقابت برای بلاک بعدی نیز هست.
تجمیع تراکنشها در بلاک (بلاک نامزد)
سناریو: گرهٔ جینگ زنجیر را تا بلاک ۲۷۷٬۳۱۴ دارد. در حین جستوجوی جواب برای ۲۷۷٬۳۱۵، بلاک ۲۷۷٬۳۱۵ را از شبکه دریافت میکند. این رویداد پایان رقابت برای آن ارتفاع و آغاز رقابت برای ۲۷۷٬۳۱۶ است. جینگ در ۱۰ دقیقهٔ قبل چند صد تراکنش در mempool جمع کرده است. پس از اعتبارسنجی بلاک جدید، تراکنشهای آن را از mempool حذف میکند و بقیه را در یک بلاک نامزد (candidate block) میگذارد. این بلاک هنوز معتبر نیست، چون اثبات کار ندارد.
در مثال کتاب، بلاک نامزد شامل ۴۱۸ تراکنش با مجموع کارمزد ۰٫۰۹۰۹۴۹۲۸ بیتکوین است. خروجی bitcoin-cli getblock برای این بلاک فیلدهایی مانند hash، size (حدود ۲۱۸٬۶۲۹ بایت)، height، version: 2، merkleroot، tx (فهرست تراکنشها)، time، nonce (۹۲۴٬۵۹۱٬۷۵۲ در نسخهٔ نمایشدادهشده)، bits (1903a30c)، difficulty، chainwork و previousblockhash را نشان میدهد.
تراکنش coinbase
اولین تراکنش هر بلاک یک تراکنش ویژه به نام coinbase است که گرهٔ ماینر میسازد و پاداش او را میپردازد. نکات کلیدی:
- coinbase هیچ UTXOای خرج نمیکند؛ تنها یک ورودی ویژه دارد که پول را «از هیچ» میآفریند. یک خروجی دارد که به آدرس خود ماینر میپردازد.
- در مثال: «پرداخت ۲۵٫۰۹۰۹۴۹۲۸ بیتکوین به آدرس جینگ» (
1MxTkeEP2PmHSMze5tUZ1hAV3YTKu2Gh1N) = ۲۵ بیتکوین پاداش (در آن زمان) + ۰٫۰۹۰۹۴۹۲۸ کارمزد. - کارمزد کل:
Sum(Inputs) − Sum(Outputs)روی تراکنشهای بلاک. - پاداش بر اساس ارتفاع در تابع
GetBlockSubsidyمحاسبه میشود: ۵۰ × COIN (۱۰⁸ ساتوشی) و سپس شیفت دودویی به راست به تعداد نصفشدنها (halvings = nHeight / 210000)؛ اگرhalvings ≥ 64پاداش صفر است. شیفت به راست برای تقسیم بر ۲ کارآمدتر از تقسیم صحیح یا اعشاری است. برای بلاک ۲۷۷٬۳۱۶ یک نصفشدن رخ داده و پاداش ۲۵ بیتکوین است. - اگر جینگ برای خودش ۱۰۰ یا ۱۰۰۰ بیتکوین بنویسد؟ بلاک او توسط همه نامعتبر شمرده میشود و فقط برق مصرفی هدر میرود؛ او فقط وقتی پاداش را خرج میکند که بلاک مورد قبول همه باشد.
ساختار ورودی coinbase
| فیلد | ورودی عادی | ورودی coinbase |
|---|---|---|
| هش تراکنش (۳۲ بایت) | اشاره به تراکنش حاوی UTXO | همهٔ بیتها صفر (ارجاع واقعی نیست) |
| اندیس خروجی (۴ بایت) | شمارهٔ UTXO | همهٔ بیتها یک: 0xFFFFFFFF |
| اسکریپت باز (VarInt + متغیر) | اسکریپتی که شرط قفل را برآورده میکند | داده coinbase با طول ۲ تا ۱۰۰ بایت |
| شمارهٔ ترتیب (۴ بایت) | 0xFFFFFFFF |
0xFFFFFFFF |
داده coinbase
بهجز چند بایت اول، محتوا دلخواه ماینر است. ساتوشی در بلاک پیدایش (genesis) عبارت «The Times 03/Jan/2009 Chancellor on brink of second bailout for banks» را گذاشت (هم مدرکِ تاریخ و هم پیام). امروز ماینرها از آن برای extra nonce و برچسب استخر استفاده میکنند. بر اساس BIP-34، در بلاکهای نسخهٔ ۲ و بالاتر، ابتدای این فیلد باید ارتفاع بلاک باشد (بهصورت دستور push).
رمزگشایی نمونه (03443b0403858402062f503253482f):
03: سه بایت بعدی را روی پشته push کن؛443b04: ارتفاع بلاک بهصورت little-endian؛ معکوس آن0x043b44= ۲۷۷٬۳۱۶؛0385840206: extra nonce؛2f503253482f= رشتهٔ ASCII/P2SH/: نشانهٔ پشتیبانی ماینر از BIP-16 (P2SH). در آن زمان ماینرها با گذاشتن/P2SH/از BIP-16 یا باp2sh/CHVاز BIP-17 حمایت میکردند و BIP-16 برنده شد.
کتاب با کتابخانهٔ libbitcoin یک برنامهٔ ++C کوچک نشان میدهد که coinbase بلاک پیدایش را استخراج و پیام ساتوشی را چاپ میکند.
ساخت سرایند بلاک (Block Header)
سرایند ۶ فیلد دارد:
| فیلد | اندازه | توضیح |
|---|---|---|
| Version | ۴ بایت | پیگیری ارتقاهای نرمافزار/پروتکل |
| Previous Block Hash | ۳۲ بایت | هش سرایند بلاک والد |
| Merkle Root | ۳۲ بایت | ریشهٔ درخت مرکل تراکنشها |
| Timestamp | ۴ بایت | زمان تقریبی ساخت (ثانیه از Unix epoch) |
| Target (bits) | ۴ بایت | هدف اثبات کار |
| Nonce | ۴ بایت | شمارندهٔ اثبات کار |
در مثال: نسخهٔ ۲ (0x02000000 در little-endian)؛ prevhash هش بلاک ۲۷۷٬۳۱۵ (0000000000000002a7bb...0569). انتخاب والد یعنی ماینر با قدرت استخراج خود به زنجیری که به آن بلاک ختم میشود رأی میدهد. درخت مرکل: coinbase + ۴۱۸ تراکنش = ۴۱۹ برگ؛ چون تعداد باید زوج باشد آخرین تکرار میشود (۴۲۰ برگ) و تا ریشه ترکیب جفتی انجام میشود. زمان 1388185914 برابر ۲۷ دسامبر ۲۰۱۳، ساعت ۲۳:۱۱:۵۴ UTC است. Target بهصورت «بیتهای هدف» (نماد توان/ضریب) ذخیره میشود و nonce از صفر شروع میشود. هدف: یافتن nonceای که هش سرایند را از target کمتر کند؛ باید میلیاردها یا تریلیونها مقدار آزمود.
استخراج بلاک
الگوریتم اثبات کار
تابع هش SHA256 است. هش یک ورودی با طول دلخواه را به خروجی ۲۵۶ بیتی ثابت و قطعی تبدیل میکند؛ پیدا کردن دو ورودی با خروجی یکسان (تصادم) عملاً ناممکن است و راهی جز آزمونوخطا برای ساخت هش دلخواه وجود ندارد. کتاب با مثال «I am Satoshi Nakamoto» نشان میدهد که افزودن یک nonce (۰ تا ۱۹) به انتهای عبارت هشهای کاملاً متفاوتی میسازد. اگر هدف «هش با رقم هگز صفر شروع شود» باشد، nonce=۱۳ جواب است (بهطور متوسط هر ۱۶ تلاش یک بار). بنابراین target آستانهای عددی است و هدف یافتن هشی عددی کمتر از آن است؛ target و دشواری رابطهٔ معکوس دارند.
تمثیل تاس: پرتاب دو تاس با هدف «کمتر از target». هرچه target کمتر شود پیروزی نادرتر میشود (در target=۲ فقط یک از ۳۶ پرتاب). از روی دشواری هدف میتوان کار انجامشده را برآورد کرد؛ یافتن جواب سخت ولی تأییدش با یک هش آسان است. این همان اثبات کار است.
کد پایتون سادهشدهٔ کتاب proof_of_work(header, difficulty_bits) با target = 2 ** (256-difficulty_bits) همهٔ nonceها تا ۲³² را امتحان میکند. نتایج روی لپتاپ: افزایش هر ۱ بیت دشواری زمان را دو برابر میکند (مثلاً ۲۲ بیت: ۱۳ ثانیه؛ ۲۴ بیت: ~۱۹۵ ثانیه؛ ۲۶ بیت: ~۶۶۵ ثانیه با ~۸۴ میلیون تلاش و نرخ ~۱۲۷ هزار هش در ثانیه). در زمان نگارش کتاب شبکه بهدنبال هشی کمتر از 0000000000000000029AB9... بود؛ حدود ۱٫۸ «سپتاهش» (هزار میلیارد میلیارد) در ثانیه لازم است و شبکه حدود ۳ اگزاهش بر ثانیه (EH/s) توان دارد تا هر ~۱۰ دقیقه یک بلاک پیدا شود.
نمایش target
مقدار bits = 0x1903a30c یعنی توان 0x19 و ضریب 0x03a30c. فرمول:
target = coefficient × 2^(8 × (exponent − 3))
برای مثال: 0x03a30c × 2^(8×0x16) = 0x03a30c × 2^176 که هگز آن 0x0000000000000003A30C000... است؛ یعنی هش باید بیش از ۶۰ بیت صفر پیشین داشته باشد. در این دشواری یک ماینر با ۱ TH/s بهطور متوسط هر ۸٬۴۹۶ بلاک (حدود ۵۹ روز) یک بار موفق میشود.
تنظیم مجدد دشواری (Retargeting)
ضربان قلب بیتکوین ۱۰ دقیقه برای هر بلاک است و باید دههها ثابت بماند، در حالی که قدرت محاسباتی و تعداد ماینرها دائماً تغییر میکند. بنابراین target پارامتری پویاست و بهطور خودکار و مستقل روی هر گره تنظیم میشود:
- هر ۲٬۰۱۶ بلاک (حدود دو هفته؛
TargetTimespan= ۱٬۲۰۹٬۶۰۰ ثانیه) همهٔ گرهها زمان واقعی تولید آن ۲۰۱۶ بلاک را با زمان مورد انتظار (۲۰٬۱۶۰ دقیقه) مقایسه میکنند:
New Target = Old Target × (Actual Time / 20160 min) - بلاکها سریعتر از ۱۰ دقیقه ← دشواری زیاد (target کم)؛ کندتر ← دشواری کم.
- تعدیل در هر دوره حداکثر ۴ برابر (بالا یا پایین) است (در
CalculateNextWorkRequiredبا کلمپ رویnActualTimespanبین یکچهارم و چهار برابر). عدمتعادل بزرگتر طی چند دوره حل میشود. - یک خطای off-by-one در پیادهسازی اصلی باعث میشود محاسبه بر پایهٔ ۲٬۰۱۵ بلاک باشد (سوگیری حدود ۰٫۰۵٪ بهسمت دشواری بیشتر).
نکته: target به تعداد یا ارزش تراکنشها بستگی ندارد؛ پس توان هش و برق مصرفی برای امنیت مستقل از حجم تراکنشهاست و بیتکوین میتواند بدون افزایش توان هش مقیاسپذیر شود. افزایش توان هش نمایانگر نیروهای بازار و ورود ماینرهای جدید برای پاداش است؛ تا وقتی توان کافی در دست ماینرهای صادق باشد، جلوی حملات تصاحب گرفته میشود. سودآوری عمدتاً به قیمت یک کیلوواتساعت برق به بیتکوین بستگی دارد.
استخراج موفق بلاک جینگ
جینگ چند دستگاه ASIC دارد که صدها هزار مدار SHA256 را موازی اجرا میکنند و از طریق USB یا LAN به گرهٔ او وصلاند. گره سرایند را به سختافزار میفرستد که تریلیونها nonce در ثانیه میآزماید. پس از حدود ۱۱ دقیقه یکی از دستگاهها جواب مییابد: nonce برابر ۴٬۲۱۵٬۴۶۹٬۴۰۱ هشی کمتر از target میدهد. گره بلاک را بلافاصله به همتایان میفرستد؛ آنها اعتبارسنجی و پخش میکنند و ماینرهای دیگر با دریافت بلاک تلاش خود برای این ارتفاع را رها کرده و بلاک جینگ را والد بلاک بعدی قرار میدهند، که نوعی «رأی» و تأیید آن زنجیر است.
اعتبارسنجی بلاک جدید
هر گره پیش از پخش بلاک، آن را با فهرست معیارهایی (در CheckBlock و CheckBlockHeader) بررسی میکند:
- ساختار داده نحواً صحیح باشد؛
- هش سرایند کمتر از target باشد (اعمال اثبات کار)؛
- زمان بلاک کمتر از ۲ ساعت در آینده باشد؛
- اندازه در حد مجاز باشد؛
- اولین تراکنش (و فقط آن) coinbase باشد؛
- همهٔ تراکنشها طبق همان فهرست قبلی معتبر باشند.
این اعتبارسنجی مستقل مانع تقلب ماینر است: coinbase نادرست کل بلاک را باطل میکند و ماینر هم برق مصرفی را از دست میدهد. ماینر صادق بلاکش در زنجیر میماند و پاداش میگیرد.
سوار کردن و انتخاب زنجیر بلاکها
هر گره سه مجموعه بلاک نگه میدارد: بلاکهای متصل به زنجیر اصلی، بلاکهای شاخههای فرعی و بلاکهای یتیم (والد ناشناخته). بلاک نامعتبر بلافاصله دور ریخته میشود.
- زنجیر اصلی = معتبرترین زنجیر با بیشترین اثبات کار تجمعی (معمولاً همان بیشترین طول؛ اگر دو زنجیر همطول بودند، آنکه کار بیشتر دارد).
- گره با نگاه به فیلد
previous block hash، والد را مییابد. اغلب والد «نوک» زنجیر اصلی است و زنجیر ادامه مییابد. - اگر بلاک زنجیر فرعی را ادامه دهد و کار تجمعی آن از زنجیر اصلی بیشتر شود، گره بازهمگرایی (reconvergence) میکند: زنجیر فرعی را اصلی میکند و ماینرها روی آن میسازند.
- بلاک یتیم تا رسیدن والدش در «استخر یتیمها» میماند؛ معمولاً وقتی دو بلاک نزدیک به هم بهترتیب معکوس (فرزند پیش از والد) برسند.
ماینرها با انتخاب اینکه بلاک بعدی را روی کدام زنجیر استخراج کنند «رأی» میدهند؛ هر بلاک جدید خودش یک رأی است.
فورکهای بلاکچین (طبیعی)
چون بلاکچین ساختار دادهای غیرمتمرکز است، نسخههایش همیشه یکسان نیست؛ بلاکها در زمانهای مختلف به گرههای مختلف میرسند. فورک زمانی رخ میدهد که دو بلاک نامزد برای ساخت طولانیترین زنجیر رقابت کنند، یعنی دو ماینر به فاصلهٔ کوتاهی جواب بیابند. کتاب با نمودارهای شکلدار (ستاره، مثلث، مثلث وارونه، لوزی) سناریو را نشان میدهد:
- همهٔ گرهها ستاره را نوک زنجیر میدانند (شکل ۱۰-۲).
- گره A بلاک «مثلث» و گره B بلاک «مثلث وارونه» را تقریباً همزمان مییابند؛ هر دو والدشان ستاره است و هر دو معتبرند (شکل ۱۰-۳).
- شبکه دو نیمه میشود: گره X ابتدا مثلث را دیده و آن را اصلی گرفته است؛ مثلث وارونه را بعداً دیده و بهعنوان شاخهٔ فرعی نگه میدارد. گره Y برعکس. هیچکدام «نادرست» نیست؛ فقط در گذر زمان یکی غالب میشود. ماینرها هر کدام روی نسخهٔ خود میسازند.
- با پیدا شدن بلاک بعدی (مثلاً «لوزی» روی مثلث)، زنجیر ستاره–مثلث–لوزی طولانیتر میشود و گرههای طرفدار مثلث وارونه به آن میپیوندند. تراکنشهای بلاک مغلوب دوباره به mempool میروند و بلاکهای آن شاخه یتیم میشوند (شکلهای ۱۰-۵ و ۱۰-۶).
فورکهای یکبلاکی تقریباً روزی یک بار رخ میدهند؛ فورک دوبلاکی حداکثر هر چند هفته یک بار. فاصلهٔ ۱۰ دقیقهای میان بلاکها مصالحهای است بین سرعت تسویه (تأیید سریعتر) و احتمال فورک (بلاکهای سریعتر ⇒ فورک بیشتر).
رقابت هش (Hashing Race)
ماینینگ صنعت بسیار رقابتی است و توان هش هر سال بهصورت نمایی رشد کرده است. نقاط عطف: سالهای ۲۰۱۰ و ۲۰۱۱ گذار از CPU به GPU و FPGA، و در ۲۰۱۳ ورود ASIC (SHA256 مستقیماً روی سیلیکون) که یک دستگاه سادهاش از کل شبکهٔ ۲۰۱۰ قویتر بود. رشد توان هش شبکه در پنج–هشت سال اول:
| سال | بازه توان هش | رشد تقریبی |
|---|---|---|
| ۲۰۰۹ | ۰٫۵ → ۸ MH/s | ۱۶× |
| ۲۰۱۰ | ۸ MH/s → ۱۱۶ GH/s | ۱۴٬۵۰۰× |
| ۲۰۱۱ | ۱۶ GH/s → ۹ TH/s | ۵۶۲× |
| ۲۰۱۲ | ۹ → ۲۳ TH/s | ۲٫۵× |
| ۲۰۱۳ | ۲۳ TH/s → ۱۰ PH/s | ۴۵۰× |
| ۲۰۱۴ | ۱۰ → ۳۰۰ PH/s | ۳۰۰۰× |
| ۲۰۱۵ | ۳۰۰ → ۸۰۰ PH/s | ۲۶۶× |
| ۲۰۱۶ | ۸۰۰ PH/s → ۲٫۵ EH/s | ۳۱۲× |
دشواری نیز بهموازات رشد کرده است. تراشههای ASIC به ۱۶ نانومتر (و هدف ۱۴ نانومتر) رسیدهاند و صنعت به مرز قانون مور رسیده است؛ دیگر جهش بزرگ ممکن نیست و رقابت به تراکم مراکز داده (چند تراشه در یک ساختمان با خنکسازی و برق کافی) منتقل شده است.
راهحل Extra Nonce
در ابتدا ماینر فقط nonce را تا ۲³² پیمایش میکرد و در صورت اتمام، timestamp را بهروز میکرد. اما با سختافزارهای بالای ۴ GH/s فضای nonce در کمتر از یک ثانیه تمام میشد و timestamp هم نمیتواند زیاد به آینده برود. راهحل از ۲۰۱۲: استفاده از فیلد coinbase (۲ تا ۱۰۰ بایت) بهعنوان extra nonce. چون coinbase در درخت مرکل است، هر تغییر آن merkle root و در نتیجه سرایند را عوض میکند. ۸ بایت extra nonce بهعلاوهٔ ۴ بایت nonce استاندارد حدود ۲⁹۶ حالت در ثانیه بدون دستزدن به timestamp میدهد و فضای بیشتری هم برای توسعه هست.
استخرهای استخراج (Mining Pools)
ماینر انفرادی (solo) عملاً شانسی ندارد، مثل بختآزمایی. مثال کتاب (۲۰۱۷): سختافزاری با ۱۴ TH/s، قیمت حدود ۲٬۵۰۰ دلار، مصرف ~۱٬۳۷۵ وات (حدود ۳۲ kWh در روز؛ ۱ تا ۲ دلار در روز با برق ارزان). یافتن یک بلاک بهطور متوسط هر ~۴ سال؛ با پاداش ۱۲٫۵ BTC و قیمت ~۱٬۰۰۰ دلار، درآمد ۱۲٬۵۰۰ دلار که حتی هزینهٔ سختافزار و برق را پوشش نمیدهد (ضرر حدود ۱٬۰۰۰ دلار) و دشواری هم همزمان بالا میرود. اگر همین ماینر عضو استخر شود، بهجای یک جایزهٔ هر چهار سال، حدود ۵۰ تا ۶۰ دلار در هفته میگیرد؛ هزینهها را تدریجی بازمیگرداند. حتی با این حال فقط با برق بسیار ارزان (زیر ۱ سنت به ازای kW) و در مقیاس بزرگ توجیه دارد.
سازوکار: ماینرها حساب میسازند و سختافزار را به سرور استخر وصل میکنند. پاداش بلاک به آدرس استخر میرود و پس از رسیدن سهم هر فرد به آستانهای، پرداخت میشود؛ اپراتور درصدی کارمزد میگیرد. برای اندازهگیری مشارکت، استخر target آسانتری (معمولاً بیش از ۱٬۰۰۰ برابر آسانتر از شبکه) تعیین میکند و هر هش زیر این هدف یک سهم (share) است که با همان اثبات کار گواه کار واقعی است. وقتی یکی از اعضا هشی زیر target شبکه بیابد، استخر پاداش را متناسب با سهمها تقسیم میکند. تمثیل تاس: هدف شبکه «کمتر از ۴»، هدف استخر «کمتر از ۸».
استخرهای مدیریتشده
اغلب استخرها توسط یک شرکت/فرد (اپراتور) اداره میشوند. سرور استخر به یک یا چند گرهٔ کامل وصل است و بلاکها و تراکنشها را برای اعضا اعتبارسنجی میکند، که اعضا را از نگهداری گرهٔ کامل (حداقل ~۱۰۰–۱۵۰ گیگابایت دیسک و ۲–۴ گیگابایت RAM، نگهداری و ارتقای مداوم) بینیاز میکند. پروتکلها: Stratum (STM) و GetBlockTemplate (GBT) که قالب سرایند بلاک نامزد (تراکنشها + coinbase با فضای extra nonce + merkle root + prev hash) میسازند؛ پروتکل قدیمی GetWork (GWK) از اواخر ۲۰۱۲ برای نرخهای بالای ۴ GH/s ناکارآمد و منسوخ شد.
استخر نظیربهنظیر (P2Pool)
استخرهای مدیریتشده خطر تقلب اپراتور (مثلاً دوبارهخرج یا باطلکردن بلاکها) و نقطهٔ شکست واحد (از کار افتادن سرور یا حملهٔ منع خدمت) دارند. در ۲۰۱۱ P2Pool ارائه شد: استخر بدون اپراتور مرکزی با زنجیر سهم (share chain)، یعنی بلاکچینی با دشواری کمتر که هر ۳۰ ثانیه یک «بلاک سهم» میسازد و سهم هر عضو را ثبت میکند. وقتی یکی از این بلاکهای سهم به target بیتکوین هم برسد، در بلاکچین اصلی ثبت و پاداش بین مشارکتکنندگان تقسیم میشود. هر عضو بلاک نامزد خود را میسازد (مثل ماینر انفرادی) ولی روی زنجیر سهم همکاری میکند؛ پرداختها ریزتر از solo و کنترل کمتر در دست اپراتور است. هزینه: پیچیدگی بیشتر (گرهٔ کامل + نرمافزار P2Pool) و آسیبپذیری نظری زنجیر سهم به حملهٔ ۵۱٪. P2Pool مشکل حملهٔ ۵۱٪ خود بیتکوین را حل نمیکند ولی اکوسیستم استخراج را متنوعتر و مقاومتر میکند.
حملات اجماع (Consensus Attacks)
اجماع بر صداقت اکثریت ماینرها از سر منفعت شخصی تکیه دارد. اگر ماینر یا گروهی سهم قابلتوجهی از توان هش بگیرد، نظریاً میتواند امنیت یا دسترسپذیری را مختل کند. محدودیتهای مهم:
- حمله فقط اجماع آینده یا حداکثر چند ده بلاک اخیر را تحتتأثیر قرار میدهد؛ دفتر کل با گذر زمان تغییرناپذیرتر میشود.
- امنیت کلیدهای خصوصی و الگوریتم امضا (ECDSA) را نمیشکند. مهاجم نمیتواند بیتکوین بدزدد، بدون امضا خرج کند یا مالکیت گذشته را عوض کند.
- مهاجم فقط میتواند تراکنشهای خودش را دوبارهخرج (double spend) کند، چون فقط برای آنها امضای معتبر دارد.
حملهٔ ۵۱٪
گروهی با اکثریت توان هش میتواند فورک عمدی بسازد و (۱) تراکنشهای خود را دوبارهخرج کند یا (۲) علیه تراکنشها/آدرسهای مشخص منع خدمت اعمال کند (نادیدهگرفتن و بازاستخراج بلاکهای حاوی آنها). دوبارهخرج دو شکل دارد: پیش از تأیید، یا با بهرهگیری از فورک برای لغو چند بلاک.
مثال مالوری: مالوری در گالری کارول، تابلوی سهتکهای «آتش بزرگ» را به ۲۵۰٬۰۰۰ دلار بیتکوین میخرد. کارول پس از فقط یک تأیید تابلوها را تحویل میدهد. همدست مالوری، پل، که استخر بزرگی دارد، به محض ورود تراکنش به بلاک، استخر را وادار میکند همان ارتفاع را دوباره استخراج کند و بهجای پرداخت به کارول تراکنشی بسازد که همان UTXO را به کیف پول مالوری برمیگرداند؛ سپس بلاک اضافی میسازد تا زنجیر جدید بلندتر شود. فورک به نفع زنجیر جدید حل میشود و کارول هم تابلو را از دست داده هم پول را. اعضای استخر ممکن است اصلاً متوجه نشوند.
دفاع: فروشندهٔ کالای گرانقیمت باید دستکم ۶ تأیید صبر کند یا از حساب escrow چندامضایی (multisig) استفاده کند و پس از تأمین مالی آن چند تأیید بگیرد. برای اقلام بسیار ارزشمند حتی ۲۴ ساعت (~۱۴۴ تأیید) منطقی است. (کافهدار کوچک میتواند بدون تأیید قهوه بفروشد، مانند کافههایی که پرداخت کارتی زیر ۲۵ دلار را بدون امضا میپذیرند.)
نکات تکمیلی دربارهٔ ۵۱٪:
- ۵۱٪ آستانهٔ تقریباً قطعی موفقیت است، نه شرط لازم؛ با سهم کمتر احتمال موفقیت کمتر است. مطالعات آماری حملاتی را با کمتر از ۳۰٪ توان هش ممکن میدانند. هرچه توان بیشتر، فورک عمیقتر یا کنترل بلاکهای آینده بیشتر.
- رشد عظیم توان هش، حملهٔ یک ماینر انفرادی را عملاً ناممکن کرده است. اما تمرکز استخرها خطر حملهٔ سودجویانهٔ اپراتور استخر را ایجاد میکند؛ چون او ساخت بلاک و انتخاب تراکنش را کنترل میکند و میتواند بهصورت محدود و نامحسوس تراکنشی حذف یا دوبارهخرج کند.
- حملهگران غیرسودجو (مثلاً دولتها با سرمایهٔ بزرگ) میتوانند با خرید سختافزار، نفوذ به اپراتورها و حملهٔ منع خدمت به استخرها بیتکوین را مختل کنند؛ این سناریوها نظریاند و با رشد نمایی توان هش غیرعملیتر میشوند.
- حملهٔ جدی اعتماد را کوتاهمدت و احتمالاً قیمت را کاهش میدهد، اما جامعه بیدرنگ پاسخ مقابلهای ارائه میدهد و سامانه مقاومتر میشود.
تغییر قواعد اجماع
قواعد اجماع اعتبار تراکنش و بلاک را تعیین میکنند و باید در کوتاهمدت بین همهٔ گرهها ثابت باشند، اما در بلندمدت برای ویژگیها، بهبودها و رفع باگ تغییر میکنند. ارتقای سامانهٔ اجماع بسیار دشوارتر از نرمافزار معمولی است و هماهنگی همهٔ شرکتکنندگان را میطلبد.
فورک سخت (Hard Fork)
علاوه بر فورک طبیعی، فورک سخت زمانی است که قواعد اجماع تغییر کند و شبکه بازهمگرا نشود: دو زنجیر مستقل ادامه مییابند. این رخداد وقتی است که بخشی از شبکه با قواعد متفاوتی کار میکند (به دلیل باگ یا تغییر عمدی). گرههای ارتقانیافته نمیتوانند در اجماع شرکت کنند؛ تغییر «سازگار با آینده (forward compatible)» نیست.
مثال کتاب: در بلندی ۴ یک فورک طبیعی یکبلاکی رخ میدهد و با بلاک ۵ حل میشود (شکل ۱۰-۹). در بلندی ۶، نسخهٔ جدیدی با نوع امضای «Smores» (غیر ECDSA) از بلاک ۷ به بعد پذیرفته میشود. ماینری با نرمافزار جدید بلاک 7b را با چنین تراکنشی استخراج میکند. گرههای قدیمی آن تراکنش و بلاک را نامعتبر میدانند، رد میکنند و روی والد (بلاک ۶) بلاک 7a را میسازند. دو زنجیر «a» و «b» از هم دور میشوند؛ حتی بلاک 8b بدون امضای Smores هم برای گرههای قدیمی یتیم است، چون والدش 7b را نمیشناسند.
فورک نرمافزاری، شبکهای، استخراجی و زنجیری: «فورک» برای توسعهدهندگان معنای دیگری هم دارد (انشعاب پروژهٔ متنباز). فورک سخت در چهار مرحله شکل میگیرد: فورک نرمافزار ← فورک شبکه (گرههای قدیمی گرههای فرستندهٔ دادهٔ نامعتبر را موقتاً ban میکنند و شبکه دو پاره میشود) ← فورک استخراج (ماینرهای قواعد جدید و قدیم روی بلاکهای متفاوت میسازند) ← فورک زنجیر. نمونههای فورک نرمافزار که به فورک سخت نرسیدند: Bitcoin XT، Bitcoin Classic و Bitcoin Unlimited. فورک سخت ناخواستهای هم هنگام ارتقا از Bitcoin Core 0.7 به 0.8 بهخاطر محدودیت Berkeley DB رخ داد؛ یعنی قواعد اجماع میتوانند بهصورت ضمنی و پیشبینینشده هم متفاوت شوند.
انحراف ماینرها و دشواری: فرض کنید توان هش ۸۰٪/۲۰٪ تقسیم شود و فورک درست پس از یک retarget رخ دهد. دشواری هر دو زنجیر یکسان به ارث میرسد. زنجیر ۸۰٪: توان کل ۲۰٪ کم شده، پس بلاکها هر ۱۲ دقیقه؛ ۲۰۱۶ بلاک ≈ ۲۴٬۱۹۲ دقیقه ≈ ۱۶٫۸ روز تا retarget بعدی. زنجیر ۲۰٪: بلاک هر ۵۰ دقیقه، و تا retarget ۱۰۰٬۸۰۰ دقیقه ≈ ۱۰ هفته؛ ظرفیت تراکنش نیز ۵ برابر کمتر میشود.
فورکهای سخت پرمناقشه: فورک سخت ریسکدار است، چون اقلیت را مجبور به ارتقا یا ماندن روی زنجیر اقلیت میکند و خطر دو شدن سامانه دارد. بسیاری از توسعهدهندگان جز با حمایت تقریباً اجماعی از آن استفاده نمیکنند؛ بحث پرتنشی (بهویژه حول حد اندازهٔ بلاک) وجود دارد: برخی مخالف مطلق فورک سخت، برخی آن را ابزار ضروری برای پرهیز از «بدهی فنی» و گسست تمیز، و برخی طرفدار استفادهٔ نادر و برنامهریزیشدهاند.
فورک نرم (Soft Fork)
همهٔ تغییرات قواعد باعث فورک سخت نیستند؛ فقط تغییرات ناسازگار با آینده. اگر کلاینت ارتقانیافته همچنان تراکنش/بلاک جدید را طبق قواعد قدیم معتبر ببیند، تغییر بدون فورک ممکن است. فورک نرم تغییری سازگار با آینده است. نکتهٔ مهم: فورک نرم فقط میتواند قواعد را محدودتر کند، نه گستردهتر؛ تراکنشها/بلاکهای ساختهشده با قواعد جدید باید طبق قواعد قدیم هم معتبر باشند (ولی عکس آن نه).
- بازتعریف opcodeهای NOP: Bitcoin Script ده opcode رزرو (NOP1 تا NOP10) دارد که بیاثرند. فورک نرم میتواند معنای یکی را عوض کند؛ مثلاً BIP-65 (CHECKLOCKTIMEVERIFY) از NOP2 استفاده کرد و قفل زمانی مطلق را روی UTXOهای حاوی آن اعمال کرد؛ برای کلاینت قدیمی همان NOP نادیده گرفته میشود.
- روشهای دیگر: سگویت (SegWit) که اسکریپت باز (witness) را از تراکنش جدا میکند، ابتدا فورک سخت در نظر گرفته شد، اما در نوامبر ۲۰۱۵ راهی برای ارائهٔ آن بهصورت فورک نرم پیشنهاد شد: اسکریپت قفل UTXOهای سگویت برای کلاینتهای قدیمی با هر اسکریپت بازی «قابل خرج» دیده میشود (جزئیات در پیوست D).
انتقادها به فورک نرم:
- بدهی فنی: از فورک سخت پیچیدهترند و هزینهٔ نگهداری و احتمال باگ را بالا میبرند؛
- سستشدن اعتبارسنجی: کلاینتهای ارتقانیافته تراکنشها را بدون ارزیابی قواعد جدید معتبر میدانند؛
- ارتقای بازگشتناپذیر: اگر فورک نرم فعالشده معکوس شود، تراکنشهای ساختهشده با قواعد جدید (مثلاً CLTV بدون قید زمانی) میتوانند به از دست رفتن وجوه بینجامند.
علامتدهی فورک نرم با نسخهٔ بلاک
فعالسازی فورک نرم از طریق علامتدهی آمادگی ماینرها است: اکثریت باید آمادهٔ اعمال قواعد جدید باشند.
BIP-34 (مارس ۲۰۱۳): از فیلد version بلاک استفاده کرد (قبلاً قراردادی ۱). این BIP ارتفاع بلاک را در coinbase اجباری کرد و نسخه ≥ ۲ میخواست. فعالسازی دومرحلهای روی پنجرهٔ غلتان ۱٬۰۰۰ بلاک:
- وقتی ۷۵٪ (۷۵۰ از ۱٬۰۰۰) بلاکها نسخهٔ ۲ بودند، بلاکهای نسخهٔ ۲ باید ارتفاع را در coinbase داشته باشند (نسخهٔ ۱ همچنان پذیرفته است؛ هر دو قاعده همزیستی دارند)؛
- وقتی ۹۵٪ (۹۵۰ از ۱٬۰۰۰) نسخهٔ ۲ شدند، بلاکهای نسخهٔ ۱ نامعتبر میشوند.
همین الگو دو بار دیگر به کار رفت: BIP-66 (کدگذاری سختگیرانهٔ DER امضا؛ نسخهٔ ۳) و BIP-65 (CHECKLOCKTIMEVERIFY؛ نسخهٔ ۴). سپس بازنشسته شد.
BIP-9: مشکلات روش قبلی: فقط یک فورک نرم در هر زمان (بهخاطر عدد صحیح نسخه)، دشواری رد یک پیشنهاد و ارائهٔ دیگری، و کاهش بیبازگشت نسخههای آزاد. BIP-9 فیلد نسخه را بهصورت بیتفیلد تفسیر میکند؛ از ۳۲ بیت، ۲۹ بیت آزاد است و میتوان همزمان روی ۲۹ پیشنهاد علامت داد. همچنین مهلت (TIMEOUT) دارد؛ اگر تا آن زمان فعال نشود رد میشود و میتوان با بیت دیگری دوباره مطرح کرد؛ بیتها پس از پایان قابل بازیافتاند (البته توصیه میشود تا استفاده از هر ۲۹ بیت بازیافت نشود). هر پیشنهاد با فیلدهای name، bit (۰ تا ۲۸)، starttime و endtime (بر پایهٔ Median Time Past) معرفی میشود.
شمارش علامتها در بازههای کامل ۲٬۰۱۶ بلاکی (دورهٔ retarget) انجام میشود: اگر در یک دوره بیش از ۹۵٪ (۱۹۱۶ از ۲۰۱۶) علامت بدهند، پیشنهاد یک دوره بعد فعال میشود. وضعیتها: DEFINED ← STARTED (پس از starttime) ← LOCKED_IN (عبور از آستانه) ← ACTIVE (یک دوره بعد، دائمی)؛ و در صورت پایان مهلت بدون رسیدن به آستانه FAILED (رد، دائمی). نخستین کاربرد BIP-9 فعالسازی csv (CHECKSEQUENCEVERIFY با BIPهای ۶۸، ۱۱۲، ۱۱۳) در ژوئیهٔ ۲۰۱۶ بود.
توسعهٔ نرمافزار اجماع
بیتکوین مرجعی برای تحمیل اراده ندارد؛ قدرت میان چند گروه پخش است: ماینرها، توسعهدهندگان هسته، توسعهدهندگان کیف پول، صرافیها، تجار و کاربران نهایی. هیچکدام یکجانبه نمیتوانند تصمیم بگیرند. ماینرها نظریاً با ۵۱٪ قواعد را عوض میکنند، اما اگر دیگران نپذیرند فعالیت اقتصادی روی زنجیر اقلیت میماند و ماینرها «سکهای بیارزش» با بلاکهای خالی خواهند داشت. بنابراین وضع موجود حالت پایدار است و فقط با اجماع بسیار گسترده تغییر ممکن است؛ آستانهٔ ۹۵٪ برای فورک نرم بازتاب همین واقعیت است. فورک نرم یا سخت هر دو مصالحه و ریسک دارند و راهحل کامل نیست. نویسنده میگوید تغییر دشوار است و اجماع مجبور به سازش میکند؛ برخی این را ضعف میدانند اما در نگاه او با گذر زمان میتوان آن را بزرگترین قوت سامانه دید.
جمعبندی
- ماینینگ مکانیزم امنیت غیرمتمرکز بیتکوین است؛ خلق سکه صرفاً انگیزهٔ مشارکت است. عرضه با نصفشدن هر ۲۱۰٬۰۰۰ بلاک کاهش مییابد و سقف حدود ۲۱ میلیون تا ~۲۱۴۰ میرسد؛ سپس کارمزد تنها انگیزه است.
- اجماع از چهار فرایند مستقل پدید میآید: اعتبارسنجی تراکنش، تجمیع در بلاک با اثبات کار، اعتبارسنجی بلاک، و انتخاب زنجیر با بیشترین کار تجمعی.
- ماینر یک بلاک نامزد با تراکنش coinbase (پاداش + کارمزد، با ارتفاع و extra nonce در داده coinbase) و سرایند ۶ فیلدی میسازد و با تکرار هش SHA256 روی nonce بهدنبال هشی کمتر از target میگردد؛ یافتن سخت و تأیید آسان است.
- دشواری هر ۲۰۱۶ بلاک (حداکثر ۴ برابر) بهطور خودکار تنظیم میشود تا میانگین بلاک ۱۰ دقیقه بماند؛ قدرت هش از CPU تا ASIC به اگزاهش رسیده و به extra nonce و استخرها (مدیریتشده، Stratum/GBT، P2Pool) انجامیده است.
- فورکهای طبیعی معمولاً ظرف یک بلاک با انتخاب زنجیر با کار بیشتر حل میشوند. حملهٔ ۵۱٪ میتواند تراکنشهای اخیر را دوبارهخرج یا سانسور کند، اما کلید خصوصی و گذشتهٔ عمیق را تهدید نمیکند؛ دفاع: ۶+ تأیید یا escrow چندامضایی.
- تغییر قواعد: فورک سخت ناسازگار و تقسیمکنندهٔ شبکه است؛ فورک نرم سازگار با آینده و فقط محدودکننده است و با علامتدهی (BIP-34 با آستانهٔ ۷۵٪/۹۵٪ و BIP-9 با بیتها، مهلت و آستانهٔ ۹۵٪) فعال میشود. تغییر دشوار است چون قدرت میان گروههای مختلف پخش است، و همین دشواری سوی قوت سامانه است.
فصل ۱۱ — امنیت بیتکوین (Bitcoin Security)
مقدمه: چرا امنیت بیتکوین متفاوت است؟
بیتکوین مثل موجودی یک حساب بانکی «ارجاع انتزاعی به ارزش» نیست؛ بیشتر شبیه پول نقد دیجیتال یا طلا است. هر که کلیدهای بازکنندهٔ بیتکوین را در اختیار داشته باشد، صاحب آن است (“تصرف” در اینجا کاملترین شکل مالکیت است). پس مثل اسکناسی که روی پیادهرو میافتد، اگر گم شود، دزدیده شود یا اشتباهی به شخص دیگری برود، هیچ مرجع بازگشتی وجود ندارد.
اما یک تفاوت مهم هست: کیف پول (حاوی کلیدها) را میتوان مثل هر فایل دیگری پشتیبانگیری کرد، در چند نسخه نگه داشت و حتی روی کاغذ چاپ کرد. این کار با پول نقد، طلا یا حساب بانکی ممکن نیست. به همین دلیل باید دربارهٔ امنیت بیتکوین به شیوهای تازه فکر کرد.
اصول امنیتی (Security Principles)
مدل متمرکز در برابر غیرمتمرکز
- در سامانههای متمرکز (بانک، شبکهٔ پرداخت کارتی) امنیت بر کنترل دسترسی و غربالگری استوار است تا افراد بد وارد نشوند.
- در بیتکوین، امنیت شبکه بر اثبات کار استوار است نه کنترل دسترسی؛ بنابراین شبکه میتواند باز باشد و ترافیک بیتکوین نیازی به رمزنگاری ندارد.
مقایسه با کارت اعتباری
شمارهٔ کارت اعتباری یک شناسهٔ خصوصی «باز» است: هرکس آن را داشته باشد میتواند بارها از حساب شما برداشت (pull) کند. بنابراین کل شبکه باید سرتاسر رمز شود، هم در مسیر و هم در ذخیرهسازی؛ و اگر مهاجمی نفوذ کند، هم تراکنشهای جاری و هم توکنهایی که برای تراکنشهای بعدی به کار میروند به خطر میافتند. نشت اطلاعات مشتریان هم آنها را در معرض سرقت هویت میگذارد.
در بیتکوین، یک تراکنش فقط مبلغ مشخصی را به گیرندهٔ مشخصی مجاز میکند؛ جعل یا تغییرش ممکن نیست، اطلاعات خصوصی (مثل هویت طرفین) را فاش نمیکند و نمیتواند پرداخت اضافهای را مجاز کند. در نتیجه میتوان تراکنش را روی یک کانال عمومی ناامن، مثل Wi-Fi باز یا بلوتوث، پخش کرد بیآنکه امنیت کم شود.
قدرت و مسئولیت کاربر
این مدل قدرت زیادی به کاربر میدهد و در عوض مسئولیت محرمانه نگه داشتن کلیدها را هم بر دوش او میگذارد. برای بیشتر کاربران، بهویژه روی دستگاههای همهمنظوره (گوشی و لپتاپ متصل به اینترنت)، این کار آسان نیست. مدل غیرمتمرکز از هک گستردهٔ یکجا (مثل نشت میلیونی کارتها) جلوگیری میکند، اما بسیاری کاربران یکییکی هک میشوند.
توسعهٔ امن سامانههای بیتکوین
مهمترین اصل برای توسعهدهندگان عدمتمرکز است. بسیاری از برنامهنویسان با مدلهای امنیتی متمرکز آشنا هستند و وسوسه میشوند همانها را در برنامهٔ بیتکوین پیاده کنند؛ نتیجه معمولاً فاجعه است. قاعدهٔ کوتاه کتاب:
کنترل کلیدها را از کاربر نگیرید و تراکنشها را از روی بلاکچین بیرون نبرید.
دو اشتباه رایج:
| اشتباه | توضیح | پیامد |
|---|---|---|
| کیف پول داغ (hot wallet) متمرکز | بسیاری از صرافیهای اولیه همهٔ وجوه کاربران را در یک کیف پول با کلیدهای ذخیرهشده روی یک سرور نگه میداشتند | کنترل از کاربران گرفته میشود و هک شدن سرور فاجعه میآفریند |
| تراکنش «خارج از بلاکچین» (off-blockchain) | برای کاهش کارمزد یا سرعتدادن، تراکنشها در دفتر کل داخلیِ متمرکز ثبت و فقط گاهی با بلاکچین همگام میشوند | دفتر کل ناایمن را میتوان بیسروصدا دستکاری کرد و ذخایر را خالی کرد |
اگر آمادهٔ سرمایهگذاری سنگین در امنیت عملیاتی، چندلایهکنترل دسترسی و ممیزی (مثل بانکها) نیستید، پیش از بیرون بردن وجوه از چارچوب امنیتی غیرمتمرکز بیتکوین خوب فکر کنید. حتی با این سرمایهگذاری، نتیجه همان مدل شکنندهٔ مالی سنتی است که از سرقت هویت، فساد و اختلاس رنج میبرد.
ریشهٔ اعتماد (Root of Trust)
در معماری امنیتی سنتی، یک هستهٔ مورد اعتماد (root of trust) پایهٔ کل سامانه است و لایههای امنیتی مثل لایههای پیاز دور آن چیده میشوند. هر لایه روی لایهٔ داخلیتر و مورد اعتمادتر با کنترل دسترسی، امضای دیجیتال و رمزنگاری بنا میشود. دلیلش این است که نرمافزار پیچیدهتر باگ بیشتری دارد؛ پس بیشترین اعتماد را به سادهترین (و کمآسیبپذیرترین) بخش میدهند. این الگو در مقیاسهای مختلف تکرار میشود: سختافزار یک دستگاه، سیستمعامل، سرویسهای سطح بالاتر و سپس چندین سرور.
در بیتکوین ماجرا فرق میکند: سازوکار اجماع یک دفتر کل عمومی کاملاً غیرمتمرکز میسازد و یک بلاکچین بهدرستی اعتبارسنجیشده، با بلاک پیدایش (genesis block) بهعنوان ریشهٔ اعتماد، زنجیرهٔ اعتماد را تا بلاک جاری پیش میبرد. توصیهها:
- برنامههای بیتکوین باید بلاکچین را ریشهٔ اعتماد خود قرار دهند و تنها چیزی که صریحاً به آن اعتماد میشود، یک بلاکچین کاملاً اعتبارسنجیشده باشد.
- اگر برنامهای (آشکار یا ضمنی) به چیز دیگری اعتماد کند، منبع آسیبپذیری است.
- روش ارزیابی: هر مؤلفه را بهنوبت فرض کنید بهطور کامل در اختیار مهاجم است و ببینید امنیت کل چه میشود. اگر برنامه بعد از به خطر افتادن یک مؤلفه ناامن شد، اعتماد در جای نادرست گذاشته شده است.
- برنامهٔ بینقص فقط باید در برابر شکست سازوکار اجماع بیتکوین آسیبپذیر باشد.
هکِ صرافیهای متعدد این نکته را تأیید میکند: آنها به اجزای بیرون از بلاکچین، مثل کیفهای داغ، پایگاههای داده دفتر کل متمرکز و کلیدهای رمزنگاری آسیبپذیر، اعتماد صریح کرده بودند.
بهترین شیوهها برای امنیت کاربر (User Security Best Practices)
انسان هزاران سال با کنترلهای امنیتی فیزیکی زندگی کرده، اما تجربهٔ امنیت دیجیتال کمتر از ۵۰ سال است. سیستمعاملهای همهمنظوره امروزی چندان ایمن نیستند و برای نگهداری پول دیجیتال طراحی نشدهاند: همیشه به اینترنت وصلاند، هزاران مؤلفهٔ نرمافزاری از صدها تولیدکننده با دسترسی گسترده به فایلها اجرا میکنند و یک نرمافزار مخرب کافی است تا کیبورد و فایلها را بدزدد و بیتکوین کیف پول را ببرد. نگهداری رایانهای عاری از ویروس و تروجان از توان اغلب کاربران خارج است. حتی سامانههای بسیار محافظتشدهٔ شرکتهای مالی و نهادهای اطلاعاتی هم مرتب نفوذ میخورند.
بیتکوین ارزش ذاتی را در یک دارایی دیجیتال میگذارد که فوری و برگشتناپذیر دزدیده میشود و نیازی به پولشویی یا تبدیل ندارد (برخلاف اطلاعات کارت و حساب بانکی که سارق باید آنها را به پول تبدیل کند)؛ این انگیزهٔ هکرها را بالا میبرد. اما از آن طرف انگیزهٔ بهبود امنیت را هم برای کاربران روشنتر میکند. در سه سال پیش از نگارش کتاب، نوآوریهای بزرگی پدید آمد: رمزنگاری سختافزاری، ذخیرهسازی کلید و کیف پولهای سختافزاری، فناوری چندامضایی (multisig) و امانتداری دیجیتال (escrow).
ذخیرهٔ فیزیکی بیتکوین و ذخیرهسازی سرد
کلیدهای بیتکوین فقط اعداد بلندی هستند؛ پس میتوان آنها را به شکل فیزیکی درآورد: چاپ روی کاغذ یا حکاکی روی سکهای فلزی. در این صورت ایمنسازی کلید همان محافظت فیزیکی از نسخهٔ چاپی است.
- مجموعهای از کلیدهای چاپشده روی کاغذ را کیف پول کاغذی (paper wallet) میگویند و ابزارهای رایگان زیادی برای ساختش هست.
- نویسنده میگوید خودش بیش از ۹۹٪ بیتکوینهایش را در کیف پولهای کاغذیِ رمزشده با BIP-38 نگه میدارد و چند نسخه را در گاوصندوقها قفل کرده است.
- نگهداری آفلاین را ذخیرهسازی سرد (cold storage) مینامند: کلیدها روی سیستمی ساخته میشوند که هرگز به اینترنت وصل نبوده و روی کاغذ یا رسانهٔ دیجیتال (مثلاً USB) آفلاین نگه داشته میشوند. این از مؤثرترین فنون امنیتی است.
کیف پولهای سختافزاری (Hardware Wallets)
به باور نویسنده، امنیت بیتکوین در بلندمدت بیشتر به شکل کیف پولهای سختافزاری ضدتخریب درمیآید. برخلاف گوشی یا رایانه، این دستگاه فقط یک کار میکند: نگهداری امن بیتکوین. نبودِ نرمافزار عمومیِ قابل نفوذ و رابطهای محدود، امنیتی تقریباً بینقص برای کاربران غیرمتخصص میدهد. مثال معرفیشده Trezor است.
موازنهٔ ریسک (Balancing Risk)
بزرگتر از ریسک سرقت، ریسک گمشدن است. فایلهای داده دائماً گم میشوند و اگر حاوی بیتکوین باشند، خسارت سنگینتر است. در ژوئیهٔ ۲۰۱۱ یک پروژهٔ شناختهشدهٔ آموزش و آگاهیرسانی بیتکوین نزدیک به ۷٬۰۰۰ بیتکوین را از دست داد: برای جلوگیری از سرقت، زنجیرهای پیچیده از پشتیبانهای رمزشده ساخته بودند و در نهایت کلیدهای رمزگشایی را گم کردند و پشتیبانها بیارزش شدند. تشبیه کتاب: مثل پنهانکردن پول با دفنکردن آن در بیابان؛ اگر بیش از حد خوب مخفی کنید، شاید دیگر پیدایش نکنید.
تنوعبخشی به ریسک (Diversifying Risk)
کسی کل داراییاش را بهصورت نقد در کیف جیبی نمیگذارد، اما بسیاری کاربران همهٔ بیتکوین خود را در یک کیف پول نگه میدارند. توصیه:
- فقط بخش کوچکی (شاید کمتر از ۵٪) را در کیف پول آنلاین یا موبایل بهعنوان «پول خرد» نگه دارید؛
- بقیه را بین چند سازوکار متنوع، مثل کیف پول دسکتاپ و ذخیرهسازی سرد، تقسیم کنید.
چندامضایی و حاکمیت (Multisig and Governance)
هر شرکت یا فردی که مقدار زیادی بیتکوین دارد باید آدرس چندامضایی را در نظر بگیرد: برای هر پرداخت بیش از یک امضا لازم است. کلیدهای امضا باید در مکانهای مختلف و در اختیار افراد مختلف باشند. مثلاً در شرکت، کلیدها مستقل ساخته میشوند و بین چند مدیر تقسیم میشوند تا هیچکس بهتنهایی نتواند وجوه را به خطر بیندازد. چندامضایی میتواند افزونگی (redundancy) هم بدهد: یک نفر چند کلید را در جاهای متفاوت نگه میدارد.
بقا و جانشینی (Survivability)
نکتهٔ مهمی که اغلب نادیده میماند دسترسپذیری در صورت ناتوانی یا مرگ صاحب کلید است. به کاربران میگویند رمز پیچیده بگذارند و کلید را از همه مخفی کنند؛ اما همین کار بازیابی را برای خانواده تقریباً ناممکن میکند و حتی ممکن است خانواده اصلاً از وجود بیتکوین خبر نداشته باشد. پیشنهادها:
- برای مقدار زیاد، جزئیات دسترسی را با یک خویشاوند مورد اعتماد یا وکیل در میان بگذارید؛
- طرح پیچیدهتر: دسترسی چندامضایی و برنامهریزی ارث با وکیلی که تخصصش «مجری دارایی دیجیتال» (digital asset executor) است.
جمعبندی
- بیتکوین مثل نقد دیجیتال است: امنیت یعنی حفاظت از کلیدهای خصوصی، و اشتباه یا سرقت قابل بازگشت نیست.
- مدل امنیتی بیتکوین غیرمتمرکز است (اثبات کار بهجای کنترل دسترسی)؛ تراکنشها نه نیاز به رمزنگاری کانال دارند و نه اطلاعات خصوصی افشا میکنند.
- توسعهدهندگان نباید کنترل کلیدها را از کاربر بگیرند یا تراکنشها را به دفتر کل بیرونی ببرند؛ ریشهٔ اعتماد باید همان بلاکچین اعتبارسنجیشده باشد و هر مؤلفهٔ دیگر باید با آزمون «اگر هک شود چه میشود؟» سنجیده شود.
- کاربران بهتر است بیشتر دارایی را در ذخیرهسازی سرد، کیف پول کاغذی رمزشده با BIP-38 یا کیف پول سختافزاری نگه دارند، ریسک را بین چند محل تقسیم کنند، برای مبالغ زیاد از چندامضایی بهره ببرند و برای فراموشی/گمشدن/مرگ برنامهٔ بازیابی داشته باشند، بیآنکه چنان امنیت را سخت کنند که خودشان هم دسترسی را از دست بدهند.
فصل ۱۲ — کاربردهای بلاکچین (Blockchain Applications)
مقدمه
امروزه واژهٔ «بلاکچین» برای هر پلتفرم برنامهای که اصول طراحی بیتکوین را دارد به کار میرود؛ اغلب هم برای چیزهایی که ویژگیهای اصلی بلاکچین بیتکوین را ندارند. این فصل بلاکچین بیتکوین را بهعنوان پلتفرم برنامهسازی بررسی میکند: ابتدا «بلوکهای سازنده» (primitives) و سپس چند کاربرد مهم: سکههای رنگی (colored coins)، کانالهای پرداخت و حالت (payment/state channels) و کانالهای پرداخت مسیریابیشده (شبکهٔ Lightning).
بیتکوین بهعنوان پول و سامانهٔ پرداخت غیرمتمرکز طراحی شد، اما در پایه مفاهیمی مانند حساب، کاربر، موجودی و پرداخت را ندارد؛ بلکه یک زبان اسکریپت تراکنشی با توابع رمزنگاری سطح پایین دارد (فصل ۶). همانطور که مفاهیم سطح بالاتر مثل حساب و پرداخت از این اجزا ساخته میشوند، کاربردهای پیچیدهٔ دیگری مثل قراردادهای هوشمند نیز قابل ساختاند. بنابراین بلاکچین بیتکوین میتواند یک پلتفرم خدمات اعتماد باشد.
بلوکهای سازنده (Building Blocks)
بیتکوین، در صورت کارکرد درست و بلندمدت، تضمینهایی میدهد که میتوان برنامهها را بر آنها بنا کرد:
| بلوک سازنده | معنا |
|---|---|
| عدم دوبارهخرج (No Double-Spend) | بنیادیترین تضمین اجماع: هیچ UTXO دو بار خرج نمیشود |
| تغییرناپذیری (Immutability) | پس از ثبت تراکنش و افزودهشدن کار کافی روی آن، داده تغییرناپذیر است؛ این تغییرناپذیری را «انرژی» تضمین میکند چون بازنویسی زنجیره به اثبات کار نیاز دارد و هرچه کار بیشتری روی بلاک انباشته شود، مقاومتر میشود |
| بیطرفی (Neutrality) | شبکه تراکنش معتبر را بدون توجه به مبدأ یا محتوا منتشر میکند؛ هرکس با کارمزد کافی میتواند تراکنش بسازد و به ثبت برساند |
| مهر زمانی امن (Secure Timestamping) | قواعد اجماع بلاکهایی با زمان خیلی قدیمی یا آینده را رد میکنند؛ مهر زمانی بلاک یعنی ورودیهای تراکنشها «پیش از این زمان خرجنشده» بودهاند |
| مجوزدهی (Authorization) | امضای دیجیتال در شبکهٔ غیرمتمرکز اعتبارسنجی میشود؛ اسکریپتِ نیازمند امضا بدون صاحب کلید اجرا نمیشود |
| قابلیت ممیزی (Auditability) | همهٔ تراکنشها عمومیاند و زنجیرهٔ بیگسست تا بلاک پیدایش دارند |
| حسابداری (Accounting) | بهجز تراکنش coinbase، مجموع ورودیها برابر مجموع خروجیها بهعلاوهٔ کارمزد است؛ ارزش از هیچ ساخته یا نابود نمیشود |
| انقضاناپذیری (Nonexpiration) | تراکنش معتبر منقضی نمیشود، مادام که ورودیها خرجنشده و قواعد اجماع ثابت بمانند |
| یکپارچگی (Integrity) | تراکنش امضاشده با SIGHASH_ALL (یا بخشهای امضاشده با انواع دیگر SIGHASH) بدون باطلشدن امضا قابل تغییر نیست |
| اتمی بودن تراکنش (Atomicity) | تراکنش یا کاملاً معتبر و ماینشده است یا نه؛ حالت میانی وجود ندارد |
| واحدهای گسسته و تقسیمناپذیر ارزش | خروجیها یا بهطور کامل خرجشدهاند یا نشدهاند و بخشی خرج نمیشوند |
| حد نصاب کنترل (Quorum of Control) | قیدهای چندامضایی M-of-N را قواعد اجماع اجرا میکنند |
| قفل زمانی/کهنگی (Timelock/Aging) | شرط اسکریپتی که قفل زمانی نسبی یا مطلق دارد تا گذشتن زمان معین اجرا نمیشود |
| تکثیر (Replication) | پس از تأیید کافی، تراکنش در شبکه تکثیر و در برابر قطع برق و از دست رفتن داده مقاوم است |
| محافظت در برابر جعل (Forgery Protection) | تراکنش فقط خروجیهای موجودِ تأییدشده را خرج میکند؛ ساخت ارزش جعلی ممکن نیست |
| سازگاری (Consistency) | بدون افراز ماینرها، احتمال بازسازماندهی یا اختلاف بر سر بلاکها با عمق، بهصورت نمایی کاهش مییابد |
| ثبت وضعیت خارجی | یک تراکنش میتواند با OP_RETURN یک مقدار داده را بهعنوان انتقال حالت در یک ماشین حالت خارجی ثبت کند |
| انتشار قابل پیشبینی (Predictable Issuance) | کمتر از ۲۱ میلیون بیتکوین با نرخ قابل پیشبینی صادر میشود |
این فهرست کامل نیست و با هر قابلیت تازه در بیتکوین بلوکهای بیشتری اضافه میشوند.
کاربردهایی که از ترکیب بلوکها ساخته میشوند
- اثبات وجود (Proof-of-Existence / دفتر اسناد دیجیتال): ترکیب تغییرناپذیری، مهر زمانی و پایداری. اثر انگشت دیجیتال (هش) سند با یک تراکنش در بلاکچین ثبت میشود و ثابت میکند که سند در آن زمان وجود داشته؛ بعداً قابل تغییر نیست و برای همیشه میماند.
- جمعسپاری (مثل Lighthouse، شبیه Kickstarter): ترکیب سازگاری، اتمی بودن و یکپارچگی. اگر برای یک تراکنش جمعآوری وجه فقط یک ورودی و خروجی (که یکپارچگی را حفظ میکند) امضا شود، دیگران میتوانند مشارکت کنند، اما تا تأمین کامل مبلغ هدف (مقدار خروجی) تراکنش قابل خرج نیست.
- کانالهای پرداخت: ترکیب حد نصاب کنترل، قفل زمانی، عدم دوبارهخرج، انقضاناپذیری، مقاومت در برابر سانسور و مجوزدهی. یک multisig ۲-از-۲ با قفل زمانی بهعنوان تراکنش «تسویه» نگه داشته میشود و هر زمان هر طرف میتواند خرجش کند، و دو طرف میتوانند «تراکنشهای تعهد» (commitment) با قفل زمانی کوتاهتر بسازند که تسویه را دوبارهخرج میکنند.
سکههای رنگی (Colored Coins)
سکههای رنگی مجموعهای از فناوریهای مشابهاند که با تراکنشهای بیتکوین، ایجاد، مالکیت و انتقال داراییهای بیرونی (extrinsic) غیر از خود بیتکوین را ثبت میکنند. «بیرونی» یعنی دارایی مستقیماً روی بلاکچین ذخیره نمیشود، در برابر بیتکوین که دارایی «درونی» است.
- داراییهای دیجیتال: سهام، مجوز، اموال مجازی (آیتم بازی)، مالکیت فکری (علامت تجاری، حق نشر).
- داراییهای فیزیکی نگهداریشده نزد اشخاص ثالث: گواهی مالکیت کالاهایی مثل طلا، نقره، نفت، سند زمین، خودرو، قایق و هواپیما.
نام آن از ایدهٔ «رنگآمیزی» مقدار اندکی بیتکوین (مثلاً یک ساتوشی) برای نمایندگی چیزی غیر از ارزش خود بیتکوین میآید. تشبیه کتاب: روی یک اسکناس ۱ دلاری بنویسید «این گواهی سهام ACME است» یا «با این میتوان یک اونس نقره گرفت» و همان را بهعنوان گواهی مالکیت معامله کنید. نخستین پیادهسازی، EPOBC (Enhanced Padded-Order-Based Coloring)، دارایی بیرونی را به یک خروجی ۱ ساتوشی نسبت میداد. پیادهسازیهای جدیدتر از OP_RETURN برای ذخیرهٔ فراداده در تراکنش و از مخازن داده بیرونی برای مرتبطکردن آن با داراییها استفاده میکنند.
دو پیادهسازی برجسته Open Assets و Colored Coins (Colu) هستند که ناسازگارند: سکهٔ ساختهشده در یکی در دیگری دیده یا استفاده نمیشود.
استفاده از سکههای رنگی
- ساخت، انتقال و مشاهده فقط با کیف پولهای ویژه ممکن است که فراداده پروتکل را تفسیر کنند.
- هرگز کلید مرتبط با سکهٔ رنگی را در کیف پول معمولی به کار نبرید؛ ممکن است فراداده را نابود کند. سکهٔ رنگی را هم نباید به آدرسهای کیف پولهای معمولی فرستاد. هر دو سامانه آدرس مخصوص سکهٔ رنگی دارند تا ارسال به کیف ناآگاه رخ ندهد.
- بیشتر مرورگرهای بلاکچین عمومی آنها را نمیبینند؛ باید از explorer مخصوص (مثل coinprism برای Open Assets، explorer مربوط به Colu و افزونهٔ Copay) استفاده کرد.
صدور (Issuance)
فرایند ساخت دارایی صدور نام دارد. یک تراکنش صدور دارایی را روی بلاکچین ثبت میکند و یک شناسهٔ دارایی (asset ID) میسازد؛ سپس با تراکنشهای انتقال بین آدرسها جابهجا میشود. ویژگیهای ممکن:
- تقسیمپذیر یا تقسیمناپذیر (مقدار صحیح مثل ۵ در برابر اعشاری مثل ۴٫۳۲۱)؛
- صدور ثابت (یکبار) یا صدور مجدد (صادرکننده بعداً واحدهای بیشتری بسازد)؛
- امکان سود سهام (dividend): توزیع پرداختهای بیتکوین بین دارندگان متناسب با سهمشان.
تراکنشهای سکهٔ رنگی
فرادادهٔ معنادهنده معمولاً در یکی از خروجیها با OP_RETURN ذخیره میشود که خروجی نشانگر (marker output) نام دارد. رمزگذاری محتوا در هر پروتکل فرق دارد و ترتیب خروجیها اهمیت مییابد:
- Open Assets: خروجیهای پیش از نشانگر، صدور و خروجیهای بعد از آن، انتقال داراییاند. نشانگر مقدار و «رنگ» را با اشاره به ترتیب خروجیها اختصاص میدهد.
- Colu: نشانگر یک کد عملیاتی (opcode) دارد: مقادیر
0x01تا0x0Fیعنی صدور (معمولاً با شناسهای برای بازیابی اطلاعات دارایی از منبع بیرونی، مثلاً bittorrent) و0x10تا0x1Fیعنی انتقال (اسکریپتهای ساده که مقدار مشخصی را از ورودیها به خروجیها، بر پایهٔ اندیس، منتقل میکنند).
اگر فراداده در OP_RETURN جا نشود، ترفندهایی هست: گذاشتن داده در redeem script بههمراه OP_DROP برای نادیدهگرفتن آن، یا multisig یک-از-N که فقط کلید اول واقعی است و بقیهٔ «کلیدها» دادههای رمزگذاریشدهاند. بدون کیف پول/explorer سازگار، چنین تراکنشی مثل تراکنش عادی با یک خروجی OP_RETURN دیده میشود.
مثال: دارایی MasterBTC
نویسنده با پروتکل Open Assets و ابزار coinprism دارایی MasterBTC را صادر کرد: کوپنی برای یک نسخهٔ رایگان از همین کتاب (۲۰ واحد صادرشده به یک آدرس ویژهٔ سکهٔ رنگی؛ آن آدرس نمونه است و ارسال به آن موجب از دست رفتن وجه میشود). نکات آموزشی:
- در coinprism صدور ۲۰ واحد دارایی دیده میشود، اما در مرورگر بلاکچینی که سکهٔ رنگی نمیفهمد (مثل blockchain.info آن زمان) همان تراکنش «عادی» است و خروجی دوم با برچسبهای «Unable to decode output address» و «Strange» مشخص میشود.
- با
bitcoin-cli decoderawtransactionمیتوان خروجی دوم را دید: مقدار صفر و اسکریپتOP_RETURNبا دادهای هگز. - پیشوند
4F41همان حروف ASCII «OA» (Open Assets) است و بعد از آن رشتهٔ متنیu=یک پیوند به تعریف دارایی است. - تعریف دارایی یک JSON است: شناسههای دارایی، نام کوتاه (MasterBTC)، نام کامل، صادرکننده (Andreas M. Antonopoulos)، توضیح،
divisibilityبرابر ۰ (تقسیمناپذیر)، نسخه و … .
Counterparty
Counterparty یک لایهٔ پروتکل بالای بیتکوین است. مانند سکههای رنگی امکان ساخت و معامله داراییها و توکنهای مجازی را میدهد و علاوه بر آن یک صرافی غیرمتمرکز برای داراییها دارد. این پروژه در حال پیادهسازی قراردادهای هوشمند مبتنی بر ماشین مجازی اتریوم (EVM) هم بود.
- فراداده را با
OP_RETURNیا آدرسهای multisig یک-از-N (که فراداده جای کلید عمومی است) در تراکنش بیتکوین جای میدهد؛ برنامههای «آگاه از Counterparty» (کیف پول، explorer یا هر برنامه با کتابخانههای آن) آن لایه را تفسیر میکنند. - بستری برای برنامههای دیگر است: Tokenly (توکنهای مالکیت دیجیتال برای تولیدکنندگان محتوا و هنرمندان برای اجاره، دسترسی، معامله و خرید)، بازی Spells of Genesis و پروژهٔ محاسبات توزیعشده Folding Coin.
- منابع: counterparty.io و مخزن CounterpartyXCP در GitHub.
کانالهای پرداخت و حالت (Payment Channels and State Channels)
کانال پرداخت سازوکاری بدوننیاز-به-اعتماد برای تبادل تراکنشهای بیتکوین بین دو طرف، خارج از بلاکچین است. این تراکنشها اگر روی بلاکچین تسویه شوند معتبرند، اما فعلاً بهعنوان «سفته» برای تسویهٔ دستهای آتی نگه داشته میشوند. چون تسویه نمیشوند، تأخیر معمول را ندارند و میتوان به گذردهی بسیار بالا، تأخیر زیر میلیثانیه و ریزدانگی در حد ساتوشی رسید.
«کانال» یک استعاره است: چیزی به نام کانال وجود ندارد، بلکه رابطه و حالت مشترک بین دو طرف خارج از بلاکچین است. مشابه جریان TCP که از بالا یک «سوکت» است ولی در واقع بستههای IP مجزاست؛ کانال پرداخت هم فقط مجموعهای از تراکنشهاست که اگر درست توالی داده شوند، تعهداتی قابلاعتماد میسازند حتی بدون اعتماد به طرف مقابل. کانال پرداخت حالت خاصی از کانال حالت (state channel) است که در آن حالتِ تغییریافته موجودی یک ارز مجازی است و با تسویهای نهایی در بلاکچین تضمین میشود.
مفاهیم و اصطلاحات پایه
- تراکنش تأمین (funding / anchor transaction): حالت مشترک را روی بلاکچین قفل میکند (در کانال پرداخت، موجودی اولیه). باید ماین شود تا کانال برقرار شود.
- تراکنشهای تعهد (commitment transactions): دو طرف تراکنشهای امضاشدهای مبادله میکنند که حالت اولیه را تغییر میدهند. اینها معتبرند و هر طرف میتواند برای تسویه ارسال کند، ولی تا بستهشدن کانال برونزنجیرهای نگه داشته میشوند. در عمل هزاران بهروزرسانی در ثانیه ممکن است.
- ابطال حالتهای قبلی: با هر تعهد جدید، حالتهای پیشین باطل میشوند تا کسی با بستن یکطرفهٔ کانال با حالت قدیمی و سودمندتر تقلب نکند.
- بستن: یا همکارانه با تراکنش تسویهٔ نهایی، یا یکطرفه با ارسال آخرین تعهد (برای وقتی که طرف مقابل ناگهان قطع شود).
در کل عمر کانال تنها دو تراکنش (تأمین و تسویه) باید ماین شوند؛ هر تعداد تعهد بین آنها هرگز دیده یا ارسال نمیشود.
مثال ساده: Emma و Fabian (کانال یکطرفه)
Fabian سرویس پخش ویدیو دارد که ثانیهای حساب میکند: ۰٫۰۱ میلیبیت (۰٫۰۰۰۰۱ BTC) در ثانیه، یعنی ۳۶ میلیبیت (۰٫۰۳۶ BTC) در ساعت. Emma کاربر است. نرمافزار (در مرورگر Emma و روی سرور Fabian) کیف پول ساده دارد و مفهوم «کانال» از دید کاربر پنهان است؛ فقط ویدیوی ثانیهبهثانیه پرداختشده را میبیند.
- دو طرف یک آدرس multisig ۲-از-۲ (P2SH، با پیشوند «3») میسازند و Emma آن را با ۳۶ میلیبیت تأمین میکند؛ این تراکنش تأمین است و ظرفیت کانال (حداکثر قابل انتقال) را تعیین میکند.
- پس از تأیید تأمین، Emma تراکنش تعهد اول را میسازد و امضا میکند: ۰٫۰۱ میلیبیت برای Fabian و ۳۵٫۹۹ بازگشت به Emma. این تراکنش فقط یک امضا (از دو) دارد؛ Fabian امضای دوم را میافزاید و همراه یک ثانیه ویدیو پس میفرستد.
- تعهد دوم همان خروجی ۲-از-۲ را خرج میکند: ۰٫۰۲ میلیبیت (در متن کتاب ۰٫۲ آمده، ولی منطقاً مجموع دو ثانیه است) به Fabian و ۳۵٫۹۸ به Emma؛ و به همین ترتیب.
- پس از مثلاً ۶۰۰ ثانیه (۱۰ دقیقه) تعهد شماره ۶۰۰: ۶ میلیبیت برای Fabian و ۳۰ برای Emma.
- با توقف پخش، هر یک از دو طرف تراکنش تسویه را ارسال میکند: Fabian پولِ ویدیوی دیدهشده را میگیرد و باقی به Emma برمیگردد.
نمونهٔ اولیهٔ این ایده در ۲۰۱۵ توسط تیمی آرژانتینی برای پخش ویدیو (streamium.io) نشان داده شد.
کانال بدوننیاز-به-اعتماد با قفل زمانی (nLocktime)
کانال بالا فقط با همکاری کامل کار میکند. دو شکست محتمل:
- پس از تأمین، Emma برای بازپسگرفتن پول به امضای Fabian نیاز دارد؛ اگر Fabian غیب شود، وجه در ۲-از-۲ گیر میکند.
- Emma میتواند تعهد قدیمیتر (مثلاً شمارهٔ ۱) را به شبکه بفرستد و برای یک ثانیه ویدیو بهجای ۶۰۰ ثانیه بپردازد.
راهحل با قفل زمانی سطح تراکنش (nLocktime):
- Emma تراکنش تأمین و تراکنش بازپرداخت را همزمان میسازد، تأمین را امضا میکند ولی منتشر نمیکند، و فقط بازپرداخت را برای امضا به Fabian میدهد. بازپرداخت همان اولین تعهد است و قفل زمانیاش (مثلاً ۳۰ روز یا ۴۳۲۰ بلاک) حد بالای عمر کانال را تعیین میکند. حالا Emma با اطمینان تأمین را منتشر میکند چون در بدترین حالت پس از پایان قفل، پولش را پس میگیرد.
- هر تعهد بعدی قفل زمانی کوتاهتر دارد (۴۳۲۰، سپس ۴۳۱۹ و …؛ تعهد ۶۰۰ حدود ۶۰۰ بلاک زودتر از تعهد ۱ معتبر میشود). بنابراین تعهد جدیدتر پیش از قبلی قابل انتشار است و با خرجکردن خروجی تأمین، قبلیها را (به کمک قاعدهٔ عدم دوبارهخرج) باطل میکند.
- در شرایط عادی، دو طرف کانال را با تراکنش تسویهٔ بدون قفل زمانی (که همان آخرین تعهد است بدون قفل) همکارانه میبندند و بلافاصله وجه را میگیرند. اگر یکی همکاری نکند، طرف دیگر مجبور به بستن یکطرفه با تعهد قفلدار است و آن هم باید منتظر بماند.
معایب این روش: (۱) عمر کانال با حداکثر قفل زمانی محدود میشود و اگر یک طرف زود ناپدید شود، دیگری باید تا ۳۰ روز برای بازپرداخت منتظر بماند؛ (۲) چون هر تعهد باید قفل را کم کند، سقف تعداد تعهدها مشخص است (مثلاً ۴۳۲۰ تا در کانال ۳۰ روزه)، و فاصلهٔ ۱ بلاکی هشیاری دائم و آنلاینبودن طرفین را میطلبد. بعداً قفلهای سطح اسکریپت (CHECKLOCKTIMEVERIFY و CHECKSEQUENCEVERIFY) انعطاف بیشتری میدهند.
تعهدهای نامتقارن ابطالپذیر (Asymmetric Revocable Commitments)
تراکنش معتبر بیتکوین منقضی یا لغو نمیشود (فقط با دوبارهخرجکردن ورودیهایش پیش از ماینشدن). راهحل بهتر: تراکنش طوری ساخته شود که استفاده از آن نامطلوب باشد؛ هر طرف یک کلید ابطال (revocation key) دارد که با آن میتواند متقلب را مجازات کند. این ایده در شبکهٔ Lightning معرفی شد.
مثال: Hitesh و Irene (دو صرافی در هند و آمریکا که پرداختهای متقابل زیادی دارند و میخواهند کارمزد و انتظار تأیید را کم کنند):
- با یک تراکنش تأمین مشترک (امضاشده توسط هر دو) هر کدام ۵ بیتکوین میگذارند: خروجی ۲-از-۲ با ۱۰ بیتکوین (ورودیها اندکی بیشتر برای کارمزد، و احتمالاً خروجی باقیمانده).
- دو تراکنش تعهد نامتقارن ساخته میشود: در تعهدی که Hitesh نگه میدارد، ۵ بیتکوینِ Irene بلافاصله به او میرسد ولی ۵ بیتکوین Hitesh فقط پس از قفل ۱۰۰۰ بلاکی با
CHECKSEQUENCEVERIFY(CSV). تعهد Irene متقارن است با نقشها جابهجا. پس هر کس بخواهد کانال را یکطرفه ببندد، خودش با تأخیر پول میگیرد. - اما تأخیر کافی نیست؛ خروجی «تأخیردار» با یک شرط
IF/ELSEساخته میشود: شاخهٔ اول با کلید ابطال (برای طرف مقابل)، شاخهٔ دوم پس از ۱۰۰۰ بلاک برای صاحب خروجی. Hitesh کلید ابطال را محرمانه نگه میدارد و فقط وقتی کانال به حالت بعدی میرود آن را به Irene میدهد. Irene دیگر با اطمینان تعهد بعدی را امضا میکند، چون اگر Hitesh حالت قدیمی را منتشر کند، Irene با کلید ابطال هر دو خروجی را میگیرد. - پروتکل دوسویه است: در هر دور، تعهدهای جدید رد و بدل و برای تعهد قبلی کلید ابطال مبادله میشود.
- مثال انتقال: مشتری Irene میخواهد ۲ بیتکوین به مشتری Hitesh بفرستد؛ حالت ۲ کانال میشود ۷ بیتکوین برای Hitesh و ۳ برای Irene. حالت ۱ (۵ و ۵) برای Irene سودمندتر بود؛ با دادن کلید ابطالِ تعهد قبلیاش به Hitesh، توان سودبردن از بازگشت به عقب را از دست میدهد.
- ابطال خودکار نیست: طرف مقابل باید بلاکچین را زیر نظر بگیرد و اگر حالت قدیمی منتشر شد، در بازهٔ ۱۰۰۰ بلاک با کلید ابطال کل ۱۰ بیتکوین را بردارد.
مزیت: کانال میتواند نامحدود باز بماند و میلیاردها تعهد داشته باشد؛ در نمونههای اولیهٔ Lightning شناسهٔ حالت ۴۸ بیتی است که بیش از ۲۸۱ تریلیون (۲٫۸×۱۰¹⁴) انتقال حالت میدهد.
قراردادهای قفل هش و زمان (HTLC)
HTLC (Hash Time Lock Contract) نوعی قرارداد هوشمند است که شرکتکنندگان وجه را به یک راز با تاریخ انقضا متعهد میکنند و در کانالهای دوسویه و مسیریابیشده به کار میرود.
- بخش هش: گیرنده راز تصادفی R میسازد و
H = Hash(R)را محاسبه میکند. H در اسکریپت قفل خروجی میآید؛ هرکس R (پیشتصویر / preimage) را بداند میتواند خرجش کند. - بخش قفل زمانی: اگر راز فاش نشود، پرداختکننده پس از مدتی با قفل زمانی مطلق (
CHECKLOCKTIMEVERIFY) بازپرداخت میگیرد. - اسکریپت ساده:
IF HASH160 <H> EQUALVERIFY ELSE <locktime> CHECKLOCKTIMEVERIFY DROP <Payee Public Key> CHECKSIG ENDIF. - در این شکل پایه، هرکس R را بداند میتواند بردارد؛ با افزودن
CHECKSIGو کلید عمومی به شاخهٔ اول میتوان فقط گیرندهٔ مشخص (که R را هم بداند) را مجاز کرد.
کانالهای پرداخت مسیریابیشده: شبکهٔ Lightning
شبکهٔ Lightning (LN) شبکهای پیشنهادی از کانالهای پرداخت دوسویه است که سر به سر به هم وصل میشوند تا هرکس بتواند پرداخت را از کانالی به کانال دیگر، بدون اعتماد به واسطهها، مسیریابی کند. نخستین بار در فوریهٔ ۲۰۱۵ توسط Joseph Poon و Thadeus Dryja تشریح شد. این نام به طراحی خاصی اشاره دارد که دستکم پنج تیم متنباز آن را پیاده کردهاند و استاندارد قابلیت همکاری آنها BOLT (Basics of Lightning Technology) است. پیادهسازیهای اولیه بهدلیل استفاده از سگویت (که هنوز در شبکهٔ اصلی فعال نبود) فقط روی testnet اجرا میشدند. طراحیهای جایگزین شامل Teechan و Tumblebit هستند.
مثال: پرداخت از Alice به Eric
پنج نفر Alice، Bob، Carol، Diana و Eric زنجیرهای از کانالها دارند: Alice–Bob، Bob–Carol، Carol–Diana، Diana–Eric؛ هر کانال با ۲ بیتکوین از هر طرف (ظرفیت ۴). Alice میخواهد ۱ بیتکوین به Eric بپردازد ولی کانال مستقیم ندارد و نمیخواهد با تراکنش تأمین جدید روی بلاکچین وجه بیشتری قفل کند.
- گرهٔ Eric راز R را تصادفی میسازد، پنهان نگه میدارد، و فقط هش H را به Alice میدهد.
- گرهٔ Alice مسیر را پیدا میکند و به Bob یک HTLC به مبلغ ۱٫۰۰۳ بیتکوین با مهلت بازپرداخت ۱۰ بلاک پیشنهاد میدهد (۰٫۰۰۳ اضافه برای کارمزد واسطهها). تعهد Alice–Bob اکنون سه خروجی دارد: ۲ برای Bob، ۰٫۹۹۷ برای Alice و ۱٫۰۰۳ در HTLC.
- Bob به Carol یک HTLC به مبلغ ۱٫۰۰۲ با مهلت ۹ بلاک میدهد (۰٫۰۰۱ سود Bob).
- Carol به Diana ۱٫۰۰۱ با مهلت ۸ بلاک میدهد.
- Diana به Eric ۱ بیتکوین با مهلت ۷ بلاک میدهد.
- Eric که R را دارد، آن را به Diana میدهد و ۱ بیتکوین را برمیدارد.
- Diana با R از Carol ۱٫۰۰۱ میگیرد (۰٫۰۰۱ کارمزد خود).
- Carol با R از Bob ۱٫۰۰۲ میگیرد.
- Bob با R از Alice ۱٫۰۰۳ میگیرد. نتیجه: Alice ۱ بیتکوین (بهعلاوهٔ ۰٫۰۰۳ کارمزد) پرداخته، واسطهها هرکدام ۰٫۰۰۱ درآمد داشتهاند و هیچکس به دیگری اعتماد نکرده است.
چون مهلتها از Alice به سوی Eric یکییکی کوتاهتر میشود، هر واسطه پس از دریافت R فرصت دارد از طرف قبلیاش مطالبه کند. اگر مسیر شکست بخورد، همهچیز به موجودیهای پیشین برمیگردد و ضرری نیست؛ تنها ریسک یک تأخیر کوچک در بازپرداخت است.
انتقال و مسیریابی در Lightning
- همهٔ ارتباط بین گرهها رمزشده نقطهبهنقطه است و هر گره یک کلید عمومی بلندمدت برای شناسه و احراز هویت دارد.
- گرهها اطلاعات مسیریابی (کانالهای باز، ظرفیت، کارمزد) را اعلام میکنند. روشها: برخی پیادهسازیها از IRC استفاده میکردند؛ برخی مدل P2P با «پخش سیلابی (flooding)» اعلان کانالها شبیه انتشار تراکنشها؛ و طرح آینده Flare (مدل ترکیبی با «همسایگی» محلی و گرههای چراغ دوربرد).
- مسیر فقط برای فرستنده شناختهشده است. مثلاً Carol فقط یک پرداخت از Bob به Diana میبیند.
- مسیریابی پیازی (onion routing) بر پایهٔ طرح Sphinx: فرستنده مسیر را طوری میسازد که (۱) واسطه فقط بخش خودش را رمزگشایی و گام بعدی را پیدا میکند، (۲) جز گام قبلی و بعدی چیزی دربارهٔ مسیر نمیداند، (۳) طول مسیر و جایگاه خود را نمیفهمد، (۴) مهاجم شبکه نمیتواند بستههای بخشهای مختلف را به هم ربط دهد، و (۵) برخلاف Tor «گره خروجی» قابل شنود ندارد چون پرداخت اصلاً به بلاکچین نمیرود.
- Alice پیام را از آخر به اول لایهلایه رمز میکند: پیام Eric با کلید Eric، سپس لفاف Diana، Carol و Bob. Bob فقط لایه بیرونی را باز میکند و بستهٔ رمزشده را به Carol میفرستد و به همین ترتیب. هر عنصر مسیر شامل HTLC بعدی، مبلغ، کارمزد و مهلت CLTV است.
- برای پنهانماندن طول مسیر، مسیر همیشه ۲۰ گام ثابت و با داده تصادفی پر میشود؛ فقط گیرندهٔ نهایی میفهمد گام بعدی ندارد.
مزایای Lightning
Lightning یک فناوری مسیریابی لایهٔ دوم است و روی هر بلاکچینی با چندامضایی، قفل زمانی و قراردادهای ساده کار میکند. مزایا:
- حریم خصوصی: پرداختها عمومی نیستند؛ واسطهها فرستنده و گیرنده را نمیدانند.
- جایگزینپذیری (Fungibility): اعمال نظارت و فهرست سیاه سختتر میشود.
- سرعت: تسویه در میلیثانیه، چون HTLCها بدون ثبت در بلاک تسویه میشوند.
- ریزدانگی: پرداخت در حد حد غبار (dust) یا کمتر، حتی پیشنهاد واحدهای زیر ساتوشی.
- ظرفیت: چند مرتبهٔ بزرگی افزایش ظرفیت؛ سقف عملی ندارد و به ظرفیت و سرعت هر گره وابسته است.
- عملکرد بدون اعتماد: همچنان تراکنشهای بیتکوین بین همتایان بدون اعتماد.
در زمان نگارش، Lightning روی testnet مستقر بود و چند تیم با پیادهسازیهای رقیب به سمت استاندارد BOLT میرفتند. نویسنده احتمال میدهد نخستین شبکهٔ کانال پرداخت مسیریابیشده در تولید باشد.
جمعبندی
- بیتکوین فراتر از پول، مجموعهای از تضمینهای اعتماد (عدم دوبارهخرج، تغییرناپذیری، بیطرفی، مهر زمانی، مجوزدهی، قفل زمانی، چندامضایی و …) است که برنامههای گوناگون از ترکیب آنها ساخته میشوند (اثبات وجود، جمعسپاری، کانال پرداخت).
- سکههای رنگی و Counterparty با فراداده در تراکنشهای بیتکوین (بیشتر
OP_RETURNو خروجی نشانگر) داراییهای بیرونی را نمایندگی میکنند، ولی به کیف پول/explorer آگاه نیاز دارند و بین پروتکلها سازگاری نیست. - کانالهای پرداخت با یک تراکنش تأمین و یک تسویه، هر تعداد بهروزرسانی برونزنجیرهای را ممکن میکنند؛ ابطال حالتهای قدیمی یا با قفل زمانی نزولی (محدود) یا بهتر با تعهدهای نامتقارن ابطالپذیر و CSV (نامحدود) انجام میشود.
- HTLC با ترکیب هش و قفل زمانی، پرداخت مشروط به افشای راز را ممکن میکند و پایهٔ شبکهٔ Lightning است که با مسیریابی پیازی، پرداخت امن، خصوصی، سریع و ریز را بدون اعتماد به واسطهها و بدون ثبت روی بلاکچین ممکن میسازد.
پیوست A — وایتپیپر بیتکوین (The Bitcoin Whitepaper by Satoshi Nakamoto)
این پیوست متن کامل مقالهٔ «Bitcoin – A Peer-to-Peer Electronic Cash System» را بدون تغییر محتوایی (فقط قالببندی) بازچاپ میکند. مقاله حدود ۹ صفحه است و ترتیب بخشهای آن همان ترتیب ایدههاست: از مسئلهٔ اعتماد شروع میکند، به ساز و کار شبکه میرسد و با محاسبهٔ احتمال حملهٔ مهاجم تمام میشود.
چکیده (Abstract)
ساتوشی ایدهٔ یک پول نقد الکترونیکی کاملاً نظیربهنظیر (peer-to-peer) را مطرح میکند که پرداخت را مستقیم از یک طرف به طرف دیگر میرساند، بدون نهاد مالی. امضای دیجیتال بخشی از راهحل است، ولی تا وقتی برای جلوگیری از خرج مضاعف (double-spending) به شخص ثالث مورد اعتماد نیاز باشد، مزیت اصلی از دست میرود. راهحل: شبکه تراکنشها را با هش کردن در زنجیرهای از اثبات کار مبتنی بر هش «مهر زمانی» میزند؛ این سابقه بدون انجام دوبارهٔ اثبات کار قابل تغییر نیست. بلندترین زنجیره هم گواه ترتیب رویدادهاست و هم گواه آنکه از بزرگترین مجموعهٔ توان پردازشی (آن زمان CPU) آمده است. تا وقتی اکثریت توان پردازش دست گرههایی است که برای حمله همکاری نمیکنند، آنها بلندترین زنجیره را میسازند و از مهاجم جلو میافتند. ساختار شبکه حداقلی است: پیامها بهصورت «بهترین تلاش» پخش میشوند و گرهها هر زمان میتوانند بروند و برگردند و بلندترین زنجیره را مرجع آنچه در غیبتشان رخ داده بپذیرند.
۱. مقدمه (Introduction)
- تجارت اینترنتی تقریباً کاملاً به مؤسسات مالی بهعنوان واسطهٔ مورد اعتماد وابسته است. این مدل «مبتنی بر اعتماد» ضعف ذاتی دارد: معاملات واقعاً برگشتناپذیر ممکن نیست چون واسطه ناچار اختلاف را میانجیگری میکند.
- هزینهٔ میانجیگری کارمزد را بالا میبرد، حداقل اندازهٔ عملی تراکنش را بزرگ میکند و پرداختهای کوچک و گاهبهگاه را غیرممکن میسازد. امکان بازگشت یعنی نیاز به اعتماد گسترش مییابد: فروشنده باید مراقب مشتری باشد، اطلاعات اضافه میخواهد و درصدی کلاهبرداری «ناگزیر» پذیرفته میشود.
- پیشنهاد: سیستم پرداخت مبتنی بر اثبات رمزنگاری بهجای اعتماد، تا هر دو طرف مستقیم معامله کنند. تراکنشهایی که از نظر محاسباتی برگرداندنشان عملی نیست از فروشنده محافظت میکنند و سازوکارهای امانی (escrow) ساده برای محافظت از خریدار قابل افزودن است.
- هستهٔ راهحل: یک سرور مهر زمانی توزیعشدهٔ نظیربهنظیر که ترتیب زمانی تراکنشها را محاسباتی اثبات میکند. شرط امنیت: گرههای صادق در مجموع توان پردازشی بیشتری از هر گروه مهاجم همکار داشته باشند.
۲. تراکنشها (Transactions)
سکهٔ الکترونیکی را «زنجیرهای از امضاهای دیجیتال» تعریف میکند: هر مالک با امضای هشِ تراکنش قبلی بههمراه کلید عمومی مالک بعدی، سکه را منتقل میکند. گیرنده با بررسی امضاها زنجیرهٔ مالکیت را تأیید میکند. مشکل: گیرنده نمیتواند مطمئن شود مالک قبلی همان سکه را جای دیگر خرج نکرده است. راهحل مرسوم یک مرجع مرکزی (mint) است که هر سکه پس از هر معامله باید به آن برگردد؛ ولی آنگاه سرنوشت کل نظام پولی به شرکت ادارهکنندهٔ mint بسته است، درست مثل بانک. برای حذف آن، باید همهٔ تراکنشها علنی اعلام شوند و شرکتکنندگان بر سر یک تاریخچهٔ واحد از ترتیب دریافت توافق کنند؛ گیرنده باید بتواند ثابت کند در لحظهٔ تراکنش اکثریت گرهها آن را «اولین» دانستهاند. فقط اولین تراکنش شمرده میشود و تلاشهای بعدی برای خرج مضاعف بیاهمیت است.
۳. سرور مهر زمانی (Timestamp Server)
هش یک بلوک از اقلام را میگیرد و آن را بهطور گسترده منتشر میکند (مثلاً در روزنامه یا Usenet). این هش ثابت میکند داده در آن زمان وجود داشته است. هر مهر زمانی هشِ مهر قبلی را در خود دارد، پس زنجیره میسازد و هر مهر جدید مهرهای پیشین را تقویت میکند.
۴. اثبات کار (Proof-of-Work)
- بهجای روزنامه، از سیستمی شبیه Hashcash (آدام بک) استفاده میشود: جستوجوی مقداری که هشِ آن (مثلاً SHA-256) با تعداد معینی بیت صفر شروع شود. کار متوسط نسبت به تعداد بیتهای صفر نمایی است ولی راستیآزمایی با یک هش انجام میشود.
- پیادهسازی: افزایش یک nonce در بلوک تا هش بلوک شرط را برآورده کند. پس از صرف این تلاش، بلوک بدون تکرار کار تغییرپذیر نیست و با اضافه شدن بلوکهای بعدی، تغییر آن یعنی تکرار کار همهٔ بلوکهای پس از آن.
- اثبات کار مسئلهٔ «نمایندگی در رأی اکثریت» را هم حل میکند: مدل «یک آیپی، یک رأی» با ساخت آیپیهای زیاد قابل خرابکردن است، ولی اثبات کار اساساً «یک CPU، یک رأی» است. رأی اکثریت همان بلندترین زنجیره است. مهاجمی که بلوک گذشته را عوض کند باید کار آن بلوک و همهٔ بعدیها را دوباره انجام دهد و از کار گرههای صادق جلو بزند؛ احتمال موفقیت مهاجم کندتر با افزودن بلوکها بهصورت نمایی کاهش مییابد.
- برای جبران افزایش سرعت سختافزار و تغییر علاقه به اجرای گره، دشواری با میانگین متحرک و هدف «تعداد متوسط بلوک در ساعت» تنظیم میشود؛ اگر بلوکها زیادی سریع تولید شوند دشواری بالا میرود.
۵. شبکه (Network)
شش گام اجرای شبکه:
- تراکنشهای جدید به همهٔ گرهها پخش میشوند.
- هر گره تراکنشهای جدید را در یک بلوک جمع میکند.
- هر گره روی یافتن اثبات کار دشوار برای بلوک خود کار میکند.
- گرهٔ موفق بلوک را برای همه پخش میکند.
- گرهها بلوک را فقط در صورتی میپذیرند که همهٔ تراکنشهایش معتبر و خرجنشده باشند.
- پذیرش با کار روی بلوک بعدی (با هشِ بلوک پذیرفتهشده بهعنوان هش قبلی) ابراز میشود.
گرهها همیشه بلندترین زنجیره را درست میدانند. اگر دو نسخهٔ متفاوت از بلوک بعدی همزمان پخش شود، هر گره روی اولی که دیده کار میکند و شاخهٔ دیگر را نگه میدارد؛ وقتی اثبات کار بعدی پیدا شود و یک شاخه بلندتر شود، گرهها به آن میروند. پخش تراکنش لازم نیست به همهٔ گرهها برسد و پخش بلوک هم نسبت به پیامهای گمشده مقاوم است (گره با دیدن بلوک بعدی، بلوک جاافتاده را درخواست میکند).
۶. انگیزه (Incentive)
اولین تراکنش هر بلوک تراکنش ویژهای است که سکهٔ جدیدی به سازندهٔ بلوک میدهد؛ این هم انگیزهٔ حمایت از شبکه است و هم راه توزیع اولیهٔ سکه در نبود مرجع مرکزی. افزایش پایدار مقدار ثابتی سکه به استخراج طلا شباهت دارد (بهجای طلا: زمان CPU و برق). انگیزه میتواند از کارمزد هم تأمین شود: اگر ارزش خروجیهای تراکنش از ورودیها کمتر باشد، تفاوت به پاداش بلوک اضافه میشود. پس از انتشار تعداد معینی سکه، انگیزه میتواند کاملاً به کارمزد منتقل شود و سیستم بدون تورم باشد. همین انگیزه صداقت را هم تشویق میکند: مهاجم حریصی که توان بیش از کل گرههای صادق دارد، باید بین «سرقت دوبارهٔ پرداختهای خودش» و «تولید سکهٔ جدید» انتخاب کند؛ پیروی از قواعد معمولاً سودآورتر از تخریب اعتبار ثروت خود اوست.
۷. بازیابی فضای دیسک (Reclaiming Disk Space)
وقتی آخرین تراکنش یک سکه زیر بلوکهای کافی دفن شد، تراکنشهای خرجشدهٔ قبلی را میتوان دور ریخت. برای اینکه هش بلوک خراب نشود، تراکنشها در یک درخت مرکل (Merkle Tree) هش میشوند و فقط ریشه در هش بلوک میآید؛ بلوکهای قدیمی با هرس شاخهها فشرده میشوند و هشهای داخلی نیاز به ذخیره ندارند. سرایند بلوک بدون تراکنش حدود ۸۰ بایت است؛ با یک بلوک هر ۱۰ دقیقه: ۸۰ × ۶ × ۲۴ × ۳۶۵ ≈ ۴٫۲ مگابایت در سال، که با فرض حافظهٔ ۲ گیگابایتی رایانههای ۲۰۰۸ و رشد ۱٫۲ گیگابایت در سال (قانون مور) مشکلی نیست.
۸. راستیآزمایی ساده پرداخت (SPV)
کاربر میتواند بدون اجرای گره کامل پرداخت را راستیآزمایی کند: فقط نسخهٔ سرایند بلوکهای بلندترین زنجیره را نگه میدارد (با پرسوجو از گرهها تا مطمئن شود بلندترین است) و شاخهٔ مرکل تراکنش را میگیرد. خودش تراکنش را اعتبارسنجی نمیکند، اما با دیدن جایگاه آن در زنجیره میفهمد گرهای آن را پذیرفته و بلوکهای بعدی تأیید بیشتر میدهند. این روش تا وقتی گرههای صادق شبکه را کنترل میکنند قابل اتکاست و اگر مهاجم شبکه را زیر سلطه بگیرد آسیبپذیر است (با تراکنشهای ساختگی مهاجم فریب میخورد). راهکار پیشنهادی: پذیرش هشدار گرهها دربارهٔ بلوک نامعتبر. کسبوکارهایی با پرداخت زیاد باز هم گره خودشان را اجرا کنند.
۹. ترکیب و تقسیم مقدار (Combining and Splitting Value)
مدیریت تکتک سنتها ناکارآمد است؛ پس تراکنش چند ورودی و چند خروجی دارد. معمولاً یک ورودی بزرگ یا چند ورودی کوچکتر و حداکثر دو خروجی: یکی پرداخت و یکی پسدادهٔ باقیمانده (change) به فرستنده. «فناوت» (وابستگی تودرتوی تراکنشها) مشکل نیست، چون هرگز نیاز نیست نسخهٔ مستقل و کامل از تاریخچهٔ یک تراکنش را استخراج کرد.
۱۰. حریم خصوصی (Privacy)
مدل بانکی با محدودکردن دسترسی به اطلاعات حریم میسازد؛ اینجا چون همهچیز علنی است، جریان اطلاعات در جای دیگری قطع میشود: کلیدهای عمومی بینام میمانند. جهان میبیند کسی مبلغی به دیگری میفرستد ولی نمیداند چه کسی؛ مانند «tape» بورس که زمان و حجم معاملات را بدون هویت نشان میدهد. توصیه: برای هر تراکنش جفتکلید تازه. تراکنش چندورودی ناگزیر نشان میدهد ورودیها مال یک مالک بودهاند؛ خطر اینجاست که با افشای هویت صاحب یک کلید، تراکنشهای دیگر او هم لو برود.
۱۱. محاسبات (Calculations)
بخش ریاضی مقاله، که ایدهٔ آن مهمتر از فرمولهاست:
- سناریو: مهاجم میخواهد زنجیرهای جایگزین سریعتر از زنجیرهٔ صادق بسازد. حتی موفقیت او ایجاد پول از هیچ یا سرقت مال دیگران را ممکن نمیکند، زیرا گرهها تراکنش نامعتبر را نمیپذیرند؛ او فقط میتواند یکی از تراکنشهای خودش را عوض کند تا پولی را که اخیراً خرج کرده پس بگیرد.
- مدل رقابت: قدمزدن تصادفی دوجملهای (Binomial Random Walk): هر بلوک صادق فاصله را ۱+ و هر بلوک مهاجم ۱− میکند. احتمال جبران عقبماندگی مانند مسئلهٔ ورشکستگی قمارباز (Gambler’s Ruin) است. اگر p احتمال یافتن بلوک بعدی توسط گره صادق و q توسط مهاجم باشد و p > q، احتمال رسیدن مهاجم از z بلوک عقبتر برابر (q/p)^z است — یعنی با افزایش z نمایی کاهش مییابد.
- زمان انتظار گیرنده: گیرنده جفتکلید تازه میسازد و کلید عمومی را درست پیش از امضا به فرستنده میدهد تا فرستنده نتواند از قبل زنجیره بسازد. سپس منتظر میماند تراکنش در بلوکی بیاید و z بلوک پس از آن متصل شود. پیشرفت بالقوهٔ مهاجم (با فرض زمان متوسط بلوکهای صادق) توزیع پواسون با میانگین λ = z·q/p دارد. احتمال موفقیت نهایی مهاجم با جمعزدن (چگالی پواسون برای هر مقدار پیشرفت) × (احتمال جبران از آن نقطه) بهدست میآید؛ مقاله آن را بازآرایی میکند تا از جمع دنبالهٔ بینهایت پرهیز شود و برنامهٔ کوتاه C ارائه میدهد.
- نتایج نمونه: برای q = 0٫1: احتمال z=۰ برابر ۱، z=۱ حدود ۰٫۲۰۵، z=۵ حدود ۰٫۰۰۰۹ و z=۱۰ حدود ۱٫۲ در میلیون. برای q = 0٫3: z=۵ حدود ۰٫۱۷۷ و z=۵۰ حدود ۶ در ده میلیون.
- تعداد بلوک لازم برای P < 0٫001:
| سهم مهاجم (q) | ۰٫۱۰ | ۰٫۱۵ | ۰٫۲۰ | ۰٫۲۵ | ۰٫۳۰ | ۰٫۳۵ | ۰٫۴۰ | ۰٫۴۵ |
|---|---|---|---|---|---|---|---|---|
| z | ۵ | ۸ | ۱۱ | ۱۵ | ۲۴ | ۴۱ | ۸۹ | ۳۴۰ |
نکتهٔ کلیدی: هرچه مهاجم به ۵۰٪ نزدیکتر شود، انتظار لازم بهشدت (غیرخطی) بالا میرود.
۱۲. نتیجهگیری (Conclusion)
سیستمی برای تراکنش الکترونیکی بدون اتکا به اعتماد: سکه از امضای دیجیتال (کنترل مالکیت قوی ولی ناقص بدون جلوگیری از خرج مضاعف) + شبکهٔ نظیربهنظیر با اثبات کار که تاریخچهٔ عمومی تراکنشها را ثبت میکند و اگر گرههای صادق اکثریت توان را داشته باشند تغییرش عملاً غیرممکن میشود. شبکه با سادگی بیساختار خود مقاوم است: گرهها همزمان و با هماهنگی اندک کار میکنند، نیازی به هویت ندارند و پیامها به مقصد خاصی مسیریابی نمیشوند. گرهها با توان پردازشی «رأی» میدهند: بلوک معتبر را با ادامهٔ آن میپذیرند و بلوک نامعتبر را با کار نکردن روی آن رد میکنند. هر قاعده و انگیزهٔ لازم با همین سازوکار اجماع اجرا میشود.
مراجع و مجوز
مقاله به ۸ منبع ارجاع میدهد: ایدهٔ b-money از وی دای (۱۹۹۸)؛ کارهای مهرزنی دیجیتال هابر، استورنِتا، بایر، ماسیاس، آویلا و کیسکوارتر (۱۹۹۱–۱۹۹۹)؛ Hashcash آدام بک (۲۰۰۲)؛ درختهای هش رالف مرکل (۱۹۸۰)؛ و کتاب احتمالات فلر (۱۹۵۷). وایتپیپر در ۲۰۰۹ بهعنوان مستند همراه نرمافزار بیتکوین ضمیمه شد و همان مجوز MIT را دارد.
جمعبندی
وایتپیپر چهار ایدهٔ ستون بیتکوین را کنار هم میگذارد: سکه بهمثابه زنجیرهٔ امضا، مهر زمانی هشزنجیرهای، اثبات کار بهعنوان «رأی با توان پردازشی» و انگیزهٔ اقتصادی برای صداقت. تحلیل احتمالی بخش «محاسبات» توضیح میدهد چرا چند تأیید (confirmation) برای اطمینان از مبالغ بزرگتر لازم است.
پیوست B — عملگرها، ثابتها و نمادهای زبان اسکریپت تراکنش (Transaction Script Language Operators, Constants, and Symbols)
این پیوست مرجع opcodeهای زبان Script بیتکوین است (جدولها از ویکی en.bitcoin.it/wiki/Script گرفته شدهاند). Script زبانی پشتهمحور و بدون حلقه است که اسکریپت قفل (scriptPubKey) و اسکریپت باز (scriptSig) را اجرا میکند. مقدار هگز هر opcode در ستون «کد» آمده است. جدولها بر اساس دستهاند.
۱. گذاشتن مقدار روی پشته (جدول B-1)
| نماد | کد | توضیح |
|---|---|---|
OP_0 / OP_FALSE |
0x00 | آرایهٔ خالی روی پشته (به معنی «نادرست») |
| (عدد ۱ تا ۷۵) | 0x01–0x4b | N بایت بعدی را به پشته بگذار |
OP_PUSHDATA1 |
0x4c | بایت بعدی N است؛ N بایت پس از آن را push کن |
OP_PUSHDATA2 |
0x4d | دو بایت بعدی N است |
OP_PUSHDATA4 |
0x4e | چهار بایت بعدی N است |
OP_1NEGATE |
0x4f | مقدار ۱− |
OP_RESERVED |
0x50 | تراکنش نامعتبر، مگر در شاخهٔ اجرانشدهٔ IF |
OP_1 / OP_TRUE |
0x51 | مقدار ۱ |
OP_2 تا OP_16 |
0x52–0x60 | مقدار N متناظر |
۲. کنترل جریان شرطی (جدول B-2)
| opcode | کد | کار |
|---|---|---|
OP_NOP |
0x61 | هیچ |
OP_VER |
0x62 | نامعتبر مگر در IF اجرانشده |
OP_IF |
0x63 | اگر بالای پشته صفر نیست، دستورات بعدی اجرا شوند |
OP_NOTIF |
0x64 | اگر بالای پشته صفر است اجرا شوند |
OP_VERIF, OP_VERNOTIF |
0x65, 0x66 | همیشه نامعتبر (حتی در شاخهٔ اجرانشده) |
OP_ELSE |
0x67 | فقط اگر شاخهٔ قبلی اجرا نشده باشد |
OP_ENDIF |
0x68 | پایان بلوک IF/NOTIF/ELSE |
OP_VERIFY |
0x69 | بالای پشته اگر TRUE نیست تراکنش نامعتبر شود |
OP_RETURN |
0x6a | توقف و نامعتبرکردن تراکنش؛ برای ثبت داده روی خروجی غیرقابلخرج |
۳. قفل زمانی (جدول B-3)
دو opcode که قبلاً NOP بودند و با سافتفورک معنا گرفتند:
OP_CHECKLOCKTIMEVERIFY(0xb1، قبلاًOP_NOP2، BIP-65): اگر مقدار بالای پشته از فیلدnLockTimeتراکنش بزرگتر باشد، تراکنش نامعتبر است. شرایط نامعتبری دیگر: پشته خالی، مقدار منفی، ناسازگاری نوع قفل (بلوک در برابر زمان؛ آستانه ۵۰۰٬۰۰۰٬۰۰۰) بین مقدار پشته وnLockTime، یاnSequenceورودی برابر 0xffffffff. در غیر اینصورت مثلNOPادامه مییابد.OP_CHECKSEQUENCEVERIFY(0xb2، قبلاًOP_NOP3، BIP-112 بههمراه BIP-68): نامعتبر اگر قفل زمانی نسبی ورودی (ازnSequence) کوتاهتر از مقدار بالای پشته باشد.
۴. عملیات پشته (جدول B-4)
| opcode | کد | کار |
|---|---|---|
OP_TOALTSTACK / OP_FROMALTSTACK |
0x6b / 0x6c | انتقال بالاترین آیتم به/از پشتهٔ جایگزین |
OP_2DROP |
0x6d | حذف دو آیتم بالا |
OP_2DUP / OP_3DUP |
0x6e / 0x6f | کپی دو/سه آیتم بالا |
OP_2OVER |
0x70 | آیتم سوم و چهارم را به بالا کپی کن |
OP_2ROT |
0x71 | آیتم پنجم و ششم را به بالا ببر |
OP_2SWAP |
0x72 | جابهجایی دو جفت بالایی |
OP_IFDUP |
0x73 | اگر صفر نیست، بالا را کپی کن |
OP_DEPTH |
0x74 | تعداد آیتمها را push کن |
OP_DROP |
0x75 | حذف بالاترین |
OP_DUP |
0x76 | کپی بالاترین (در P2PKH کلیدی) |
OP_NIP |
0x77 | حذف دومین آیتم |
OP_OVER |
0x78 | کپی دومین به بالا |
OP_PICK / OP_ROLL |
0x79 / 0x7a | N را بردار؛ آیتم Nام را کپی/جابهجا کن به بالا |
OP_ROT |
0x7b | چرخش سه آیتم بالا |
OP_SWAP |
0x7c | جابهجایی (کتاب «سه آیتم» نوشته؛ در عمل دو آیتم بالا) |
OP_TUCK |
0x7d | بالا را کپی کن و بین بالا و دومی بگذار |
۵. عملیات رشتهای (جدول B-5)
OP_CAT (0x7e)، OP_SUBSTR (0x7f)، OP_LEFT (0x80)، OP_RIGHT (0x81) — همگی غیرفعالاند (disabled)؛ هرگز اجرا نمیشوند. فقط OP_SIZE (0x82) فعال است و طول آیتم بالا را push میکند.
۶. منطق و مقایسه (جدول B-6)
- غیرفعال:
OP_INVERT(0x83)،OP_AND(0x84)،OP_OR(0x85)،OP_XOR(0x86). OP_EQUAL(0x87): اگر دو آیتم بالا دقیقاً برابرند TRUE.OP_EQUALVERIFY(0x88):EQUALو سپسVERIFY.OP_RESERVED1/2(0x89, 0x8a): نامعتبر مگر در شاخهٔ اجرانشده.
۷. عملگرهای عددی (جدول B-7)
| opcode | کد | کار |
|---|---|---|
OP_1ADD, OP_1SUB |
0x8b, 0x8c | ۱ اضافه/کم کن |
OP_2MUL, OP_2DIV |
0x8d, 0x8e | غیرفعال (ضرب/تقسیم بر ۲) |
OP_NEGATE |
0x8f | تغییر علامت |
OP_ABS |
0x90 | قدرمطلق |
OP_NOT |
0x91 | اگر ۰ یا ۱ است معکوسش کن، وگرنه ۰ |
OP_0NOTEQUAL |
0x92 | اگر ۰ است ۰، وگرنه ۱ |
OP_ADD, OP_SUB |
0x93, 0x94 | جمع و تفریق دو آیتم بالا |
OP_MUL, OP_DIV, OP_MOD, OP_LSHIFT, OP_RSHIFT |
0x95–0x99 | غیرفعال |
OP_BOOLAND, OP_BOOLOR |
0x9a, 0x9b | AND/OR منطقی |
OP_NUMEQUAL, OP_NUMEQUALVERIFY, OP_NUMNOTEQUAL |
0x9c–0x9e | برابری/نابرابری عددی (با نسخهٔ VERIFY) |
OP_LESSTHAN, OP_GREATERTHAN, OP_LESSTHANOREQUAL, OP_GREATERTHANOREQUAL |
0x9f–0xa2 | مقایسهها |
OP_MIN, OP_MAX |
0xa3, 0xa4 | کوچکتر/بزرگتر |
OP_WITHIN |
0xa5 | TRUE اگر آیتم سوم در بازهٔ [دوم، اول) باشد |
(در متن استخراجشدهٔ کتاب توضیح ستونها در جدول B-7 به هم ریخته است؛ شرح بالا بر اساس مستند Script بازسازی شده است.)
۸. رمزنگاری و هش (جدول B-8)
| opcode | کد | کار |
|---|---|---|
OP_RIPEMD160 |
0xa6 | هش RIPEMD160 |
OP_SHA1 |
0xa7 | هش SHA1 |
OP_SHA256 |
0xa8 | هش SHA256 |
OP_HASH160 |
0xa9 | RIPEMD160(SHA256(x)) — پایهٔ آدرسها |
OP_HASH256 |
0xaa | SHA256(SHA256(x)) |
OP_CODESEPARATOR |
0xab | نشانگذاری شروع دادهای که امضا بررسی میشود |
OP_CHECKSIG |
0xac | کلید عمومی و امضا را بردار؛ اگر امضا برای هش تراکنش معتبر است TRUE |
OP_CHECKSIGVERIFY |
0xad | CHECKSIG + VERIFY |
OP_CHECKMULTISIG |
0xae | برای هر جفت امضا/کلید CHECKSIG؛ همه باید درست باشند. باگ: یک آیتم اضافی از پشته برمیدارد، لذا باید یک OP_0/NOP پیش از امضاها گذاشت |
OP_CHECKMULTISIGVERIFY |
0xaf | CHECKMULTISIG + VERIFY |
۹. غیرعملگرها و رزروشدهها (جدولهای B-9 و B-10)
OP_NOP1تاOP_NOP10(0xb0–0xb9): هیچکاری نمیکنند و نادیده گرفته میشوند؛ ذخیرهٔ اصلی برای ارتقاهای سافتفورک آینده (مثل CLTV و CSV که از NOP2 و NOP3 ساخته شدند).- نمادهای رزروشده برای تجزیهگر داخلی:
OP_SMALLDATA(0xf9)،OP_SMALLINTEGER(0xfa)،OP_PUBKEYS(0xfb)،OP_PUBKEYHASH(0xfd)،OP_PUBKEY(0xfe) وOP_INVALIDOPCODE(0xff) برای هر کد تخصیصنیافته.
جمعبندی
نکات عملی از مرور جدولها: (۱) Script عمداً محدود است؛ ضرب، تقسیم، رشتهها و بیتعملیات غیرفعالاند. (۲) opcodeهای NOP فضای ارتقای سافتفورکاند. (۳) الگوی استاندارد P2PKH از DUP HASH160 <hash> EQUALVERIFY CHECKSIG ساخته میشود. (۴) باگ CHECKMULTISIG همچنان در اجماع باقی است و راهحلش عنصر ساختگی اضافی است. (۵) OP_RETURN راه استاندارد ثبت دادهی غیرپرداختی است.
پیوست C — پیشنهادهای بهبود بیتکوین (Bitcoin Improvement Proposals)
BIP چیست؟
BIP (Bitcoin Improvement Proposal) سندی طراحی است که یا اطلاعاتی به جامعهٔ بیتکوین میدهد یا قابلیت جدیدی را برای بیتکوین، فرایندها یا محیطش توصیف میکند. مخزن رسمی و نسخهبندیشده: github.com/bitcoin/bips. بر پایهٔ BIP-1 سه نوع BIP هست:
- Standard: تغییری که بیشتر یا همهٔ پیادهسازیها را تحتتأثیر میگذارد؛ مثلاً تغییر پروتکل شبکه، قواعد اعتبار بلوک/تراکنش یا هر چیزی که قابلیت همکاری برنامهها را تغییر میدهد.
- Informational: مسئلهٔ طراحی یا راهنمای عمومی؛ ویژگی جدید پیشنهاد نمیکند و لزوماً اجماع جامعه را نشان نمیدهد، پس کاربران میتوانند نادیدهاش بگیرند.
- Process: فرایند یا تغییر در فرایندها (روالها، تصمیمگیری، ابزار توسعه). شبیه Standard ولی خارج از خود پروتکل؛ معمولاً نیازمند اجماع است و نادیدهگرفتنش آزاد نیست. هر meta-BIP هم Process است.
وضعیتهای متداول: Draft، Proposed، Final، Active (برای Process)، Deferred، Withdrawn، Rejected، Replaced و «BIP number allocated». جدول زیر خلاصهٔ بازچاپشدهٔ کتاب از عکسفوری آوریل ۲۰۱۷ است؛ برای وضعیت امروز باید مخزن را دید. بعضی ستونهای وضعیت در متن استخراجشده درهماند و با «؟» علامت خوردهاند.
۱. فرایند
| BIP | عنوان | وضعیت | توضیح |
|---|---|---|---|
| 1 | BIP Purpose and Guidelines | Process، جایگزینشده | هدف و رهنمود (با BIP-2 جایگزین شد) |
| 2 | BIP process, revised | Process، Active | روند بازبینیشدهٔ BIP (Luke Dashjr) |
| 123 | BIP Classification | Process، Active | طبقهبندی BIPها |
| 132 | Committee-based BIP Acceptance Process | Process، Withdrawn | پذیرش از طریق کمیته |
| 99 | Motivation and deployment of consensus rule changes | Informational، Draft | انگیزه و استقرار تغییر قواعد (فورک نرم/سخت) |
| 90 | Buried Deployments | Informational، Draft | «دفنکردن» استقرارهای قدیمی در کد |
۲. استقرار فورک و سافتفورک
| BIP | عنوان | وضعیت | توضیح |
|---|---|---|---|
| 8 | Version bits with guaranteed lock-in | Informational، Draft | علامتدهی نسخه با قفل تضمینی |
| 9 | Version bits with timeout and delay | Informational، Final | سازوکار علامتدهی ماینرها با بیتهای نسخه؛ مبنای استقرار سافتفورکها |
| 34 | Block v2, Height in Coinbase | Standard، Final | درج ارتفاع بلوک در coinbase |
| 50 | March 2013 Chain Fork Post-Mortem | Informational، Final | گزارش فورک ناخواستهٔ مارس ۲۰۱۳ |
| 148 | Mandatory activation of segwit deployment | Standard | فعالسازی اجباری سگویت (UASF) |
۳. اسکریپت و تراکنش
| BIP | عنوان | وضعیت | توضیح |
|---|---|---|---|
| 11 | M-of-N Standard Transactions | Final | استانداردسازی چندامضایی تا ۳ کلید |
| 12 | OP_EVAL | Withdrawn | پیشنهاد اولیهٔ اسکریپتهای ارزیابی (قبل از P2SH) |
| 13 | Address Format for pay-to-script-hash | Final | فرمت آدرس P2SH (پیشوند 3) |
| 16 | Pay to Script Hash | Final | P2SH؛ قفل بر هش اسکریپت بازخرید |
| 17 | OP_CHECKHASHVERIFY (CHV) | Withdrawn | رقیب P2SH |
| 18 | hashScriptCheck | Proposed | رقیب P2SH |
| 19 | M-of-N Standard Transactions (Low SigOp) | Draft | نسخهٔ با sigop کمتر |
| 30 | Duplicate transactions | Final | جلوگیری از تراکنشهای تکراری |
| 62 | Dealing with malleability | Withdrawn | تلاش اولیه برای مهار malleability |
| 65 | OP_CHECKLOCKTIMEVERIFY | Final | CLTV؛ قفل زمانی مطلق در اسکریپت |
| 66 | Strict DER signatures | Final | الزام رمزگذاری DER سختگیرانه |
| 68 | Relative lock-time using consensus-enforced sequence numbers | Final | قفل نسبی با nSequence |
| 112 | CHECKSEQUENCEVERIFY | Standard (؟) | CSV؛ قفل نسبی در اسکریپت |
| 113 | Median time-past as endpoint for lock-time calculations | Standard (؟) | مبنای زمان قفل: میانهٔ زمان بلوکهای اخیر |
| 114 | Merkelized Abstract Syntax Tree | Draft | MAST؛ آشکارسازی فقط شاخهٔ اجراشدهٔ اسکریپت |
| 125 | Opt-in Full Replace-by-Fee Signaling | Proposed | RBF با علامتدهی داوطلبانه |
| 199 | Hashed Time-Locked Contract transactions | Standard | HTLC (پایهٔ کانالهای پرداخت و Lightning) |
۴. کیف پول و کلید
| BIP | عنوان | وضعیت | توضیح |
|---|---|---|---|
| 32 | Hierarchical Deterministic Wallets | Informational، Final | درخت کلید از یک seed |
| 38 | Passphrase-protected private key | Draft | رمزگذاری کلید خصوصی با رمز عبور |
| 39 | Mnemonic code for generating deterministic keys | Proposed | عبارتهای بازیابی (mnemonic) |
| 43 | Purpose Field for Deterministic Wallets | Informational، Draft | فیلد purpose در مسیر HD |
| 44 | Multi-Account Hierarchy for Deterministic Wallets | Proposed | ساختار چندحسابی HD |
| 45 | Structure for Deterministic P2SH Multisignature Wallets | Proposed | کیف پول چندامضایی قطعی |
| 47 | Reusable Payment Codes for HD Wallets | Draft | کدهای پرداخت قابلاستفادهٔ مجدد |
| 49 | Derivation scheme for P2WPKH-nested-in-P2SH accounts | Draft | مسیر HD برای سگویت داخل P2SH |
| 63 | Stealth Addresses | شمارهٔ تخصیصیافته | آدرسهای پنهان (Peter Todd) |
| 67 | Deterministic P2SH multisig addresses through public key sorting | Proposed | مرتبسازی کلیدها برای آدرس یکتا |
| 80, 81 | Hierarchy for (Non-)Colored Voting Pool Deterministic Multisig Wallets | Informational، Deferred | سلسلهمراتب کیفهای استخر رأی |
| 83 | Dynamic Hierarchical Deterministic Key Trees | Draft | درختهای HD پویا |
| 124 | Hierarchical Deterministic Script Templates | Draft | قالبهای اسکریپت HD |
۵. شبکه و پیامها
| BIP | عنوان | توضیح |
|---|---|---|
| 14 | Protocol Version and User Agent (Final) | نسخهٔ پروتکل و user-agent |
| 31 | Pong message (Final) | پیام pong |
| 33 | Stratized Nodes (Draft) | لایهبندی گرهها |
| 35 | mempool message (Final) | درخواست محتوای mempool |
| 36 | Custom Services (Draft) | سرویسهای سفارشی |
| 37 | Connection Bloom filtering (Final) | فیلتر Bloom برای گرههای SPV |
| 60 | Fixed Length “version” Message (Draft) | پیام version با طول ثابت |
| 61 | Reject P2P message (Final) | پیام reject |
| 64 | getutxo message (Draft) | پرسوجوی UTXO |
| 111 | NODE_BLOOM service bit (Final) | بیت سرویس فیلتر Bloom |
| 130 | sendheaders message (Proposed) | ارسال سرایند بهجای inv |
| 133 | feefilter message (Draft) | فیلتر حداقل کارمزد |
| 150 | Peer Authentication | احراز هویت همتا |
| 151 | Peer-to-Peer Communication Encryption | رمزنگاری ارتباط P2P |
| 152 | Compact Block Relay | پخش فشردهٔ بلوک |
| 180 | Block size/weight fraud proof | اثبات تقلب اندازه/وزن بلوک |
۶. استخراج
| BIP | عنوان | وضعیت | توضیح |
|---|---|---|---|
| 22 | getblocktemplate – Fundamentals | Final | الگوی بلوک برای ماینرها |
| 23 | getblocktemplate – Pooled Mining | Final | استخراج استخری |
| 40, 41 | Stratum wire / mining protocol | شمارهٔ تخصیصیافته | پروتکل Stratum |
| 42 | A finite monetary supply for Bitcoin | Draft | رفع سرریز عرضه پس از ~۲۱۰۰۰ سال |
| 145 | getblocktemplate Updates for Segregated Witness | Draft | همین برای سگویت |
۷. اندازهٔ بلوک (بحثهای ۲۰۱۵–۲۰۱۷)
| BIP | عنوان | وضعیت |
|---|---|---|
| 101 | Increase maximum block size (Gavin Andresen) | Withdrawn |
| 102 | Block size increase to 2MB (Jeff Garzik) | Draft |
| 103 | Block size following technological growth (Pieter Wuille) | Draft |
| 104 | Block75 – Max block size like difficulty | Draft |
| 105 | Consensus based block size retargeting algorithm | Draft |
| 106 | Dynamically Controlled Bitcoin Block Size Max Cap | Draft |
| 107 | Dynamic limit on the block size | Draft |
| 109 | Two million byte size limit with sigop and sighash limits | Rejected |
۸. سگویت و malleability
| BIP | عنوان | وضعیت | توضیح |
|---|---|---|---|
| 140 | Normalized TXID | Draft/Deferred | راهکار جایگزین برای malleability |
| 141 | Segregated Witness (Consensus layer) | Draft | قواعد اجماع سگویت |
| 142 | Address Format for Segregated Witness | Draft | قالب آدرس |
| 143 | Transaction Signature Verification for Version 0 Witness Program | Draft | الگوریتم امضای جدید |
| 144 | Segregated Witness (Peer Services) | Draft | پیامها و سریالسازی جدید شبکه |
| 146 | Dealing with signature encoding malleability | Draft | مهار malleability امضا |
| 147 | Dealing with dummy stack element malleability | Draft | مهار malleability عنصر ساختگی CHECKMULTISIG |
جزئیات سگویت در پیوست D آمده است.
۹. پرداخت و URI
| BIP | عنوان | توضیح |
|---|---|---|
| 20 → 21 | URI Scheme | BIP-20 جایگزین شد؛ BIP-21 (Final) قالب bitcoin: |
| 70 | Payment Protocol (Final) | درخواست پرداخت امضاشده |
| 71 | Payment Protocol MIME types (Final) | انواع MIME |
| 72 | bitcoin: uri extensions for Payment Protocol (Final) | افزونهٔ URI |
| 73 | Use “Accept” header for response type negotiation (Final) | مذاکرهٔ نوع پاسخ |
| 74 | Allow zero value OP_RETURN in Payment Protocol (Draft) | OP_RETURN با مقدار صفر |
| 75 | Out of Band Address Exchange using Payment Protocol Encryption (Draft) | تبادل آدرس رمزنگاریشده |
| 120, 121 | Proof of Payment / URI scheme (Draft) | اثبات پرداخت |
| 122 | URI scheme for Blockchain references/exploration (Draft) | URI برای ارجاع به بلاکچین |
| 171 | Currency/exchange rate information API | API نرخ ارز |
سایر: BIP-10 (توزیع تراکنش چندامضایی، Withdrawn)، BIP-15 (Aliases، Deferred)، BIP-69 (مرتبسازی لغتنامهای ورودی/خروجی)، BIP-126 (بهترین رویهها برای تراکنشهای با ورودی ناهمگن)، BIP-131 (تراکنش «coalescing»)، BIP-134 (Flexible Transactions).
جمعبندی
BIPها مسیر رسمی تکامل بیتکویناند: نخست بحث و پیشنویس، سپس پیادهسازی و در نهایت وضعیت Final. چند BIP مبنای اجزای مهم کتاباند: BIP-32/39/44 برای کیفپول HD، BIP-16 برای P2SH، BIP-65/68/112 برای قفل زمانی، BIP-9 برای استقرار سافتفورک و BIP-141/143/144 برای سگویت.
پیوست D — شاهد جداشده (سگویت) (Segregated Witness)
(توجه: این پیوست در میانهٔ ۲۰۱۷ نوشته شده، زمانی که سگویت بهصورت سافتفورک BIP-9 هنوز در انتظار فعالسازی بود.)
۱. سگویت چیست؟
در رمزنگاری، «شاهد» (witness) پاسخ یک معماست. در بیتکوین، شاهد چیزی است که شرط رمزنگاریشدهٔ یک UTXO را برآورده میکند. امضای دیجیتال یک نوع شاهد است، ولی شاهد عمومیتر است: هر راهحلی که UTXO را باز کند؛ یعنی همان «اسکریپت باز» یا scriptSig. پیش از سگویت هر ورودی تراکنش شاهد خودش را «درونخطی» (inline) داشت. Segregated Witness یعنی جداسازی امضا/اسکریپت باز از بدنهٔ تراکنش و انتقالش به ساختاری جداگانه که کنار تراکنش حمل میشود. کلاینتها میتوانند داده را با یا بدون شاهد درخواست کنند.
BIPهای تعریفکنندهٔ آن:
- BIP-141: تعریف اصلی (لایهٔ اجماع)
- BIP-143: راستیآزمایی امضا برای witness program نسخهٔ ۰
- BIP-144: سرویسهای همتا (پیامها و قالبهای سریالسازی جدید)
- BIP-145: بهروزرسانی getblocktemplate برای استخراج
۲. چرا سگویت؟ (پنج مزیت)
- رفع malleability تراکنش: شناسهٔ تراکنش (هش) دیگر شاهد را شامل نمیشود. شاهد تنها بخشی بود که شخص ثالث میتوانست دستکاریاش کند و txid را عوض کند. اکنون هش تراکنش جز برای سازنده تغییرناپذیر است؛ این برای پروتکلهای پیشرفته مانند کانالهای پرداخت، تراکنشهای زنجیرهای و Lightning حیاتی است.
- نسخهبندی اسکریپت (script versioning): هر اسکریپت قفل با شمارهٔ نسخه شروع میشود (مثل نسخهٔ تراکنش و بلوک). بنابراین زبان اسکریپت را میتوان با سافتفورک و بهصورت سازگار با گذشته ارتقا داد (opcode، نحو یا معنای جدید) و نوآوری سریعتر میشود.
- مقیاسپذیری شبکه و ذخیرهسازی: شاهد اغلب بخش بزرگ تراکنش است؛ در اسکریپتهای پیچیده (multisig، کانالها) گاهی بیش از ۷۵٪ داده. گرهها میتوانند پس از راستیآزمایی امضاها شاهد را هرس کنند، یا در SPV اصلاً نادیده بگیرند؛ لازم نیست همهجا منتقل و ذخیره شود.
- بهینهسازی راستیآزمایی امضا: در الگوریتم قدیمی تعداد عملیات هش با اندازهٔ تراکنش متناسب بود و کل هشها با تعداد عملیات امضا O(n²) رشد میکرد (بار محاسباتی سنگین برای همهٔ گرهها). سگویت این را به O(n) کاهش میدهد.
- بهبود امضای آفلاین: امضای سگویت مبلغ هر ورودی را هم در هش امضاشونده میگنجاند. دستگاه آفلاین (مثل کیف پول سختافزاری) لازم نیست تراکنشهای قبلی ورودیها را برای بررسی مبلغ دریافت کند؛ اگر سیستم آنلاین آلوده مبلغ را دروغ بگوید، امضا نامعتبر میشود.
۳. سگویت چگونه کار میکند؟
سگویت ظاهراً ویژگی سطح تراکنش است، اما در واقع ویژگی هر خروجی است: یک تراکنش میتواند هم خروجیهای سگویت و هم سنتی را خرج کند. پس درستتر است از «ورودی سگویت» حرف بزنیم نه «تراکنش سگویت». اسکریپت قفل یک UTXO سگویت چنان تعریف میشود که با شاهدی بیرون از ورودی (segregated) برآورده شود.
سافتفورک و سازگاری رو به عقب
چنین تغییر معماریای در حالت عادی هاردفورک میطلبید (تغییر همزمان قواعد اجماع در همهٔ گرهها و کیفها). اما سگویت سافتفورک است: نرمافزار ارتقانیافته آن را نادیده میگیرد و بدون اختلال کار میکند. خروجی سگویت برای گره/کیف قدیمی «قابل خرج توسط هرکس» (anyone-can-spend) به نظر میرسد و با امضای خالی هم خرج میشود؛ پس نبود امضا در خود تراکنش آن را نامعتبر نمیکند. گرهها و ماینرهای ارتقایافته اما میدانند باید شاهد معتبر در دادهٔ شاهد باشد.
۴. نمونهها: P2WPKH و P2WSH
Pay-to-Witness-Public-Key-Hash (P2WPKH)
اسکریپت قفل P2PKH سنتی (در مثال قهوهی آلیس و باب):
DUP HASH160 <hash20> EQUALVERIFY CHECKSIG
معادل سگویت فقط دو push است:
0 <hash20>
برای کلاینت قدیمی دو push ساده و «قابل خرج با امضای خالی» است. برای کلاینت سگویتآگاه، عدد اول (۰) نسخهٔ شاهد و ۲۰ بایت دوم witness program است که همان هش کلید عمومی است. باب برای خرجکردن، scriptSig را خالی میگذارد و در بخش witness تراکنش امضا و کلید را میآورد.
هشدار مهم: P2WPKH را باید گیرنده از کلید عمومی فشرده (compressed) بسازد؛ فرستنده نباید آدرس P2PKH یا کلید فشردهنشده را به آن تبدیل کند، چون نمیداند کیف گیرنده سگویت را میفهمد و کلید فشردهنشده در سگویت غیراستاندارد است و ممکن است وجه غیرقابلخرج شود.
Pay-to-Witness-Script-Hash (P2WSH)
معادل P2SH. نمونهٔ شرکت محمد با multisig ۲-از-۳ (قفل P2SH: HASH160 <hash20> EQUAL). در سگویت:
0 <hash32>
که ۳۲ بایت، SHA256 اسکریپت بازخرید (redeem script) است. در خرجکردن، scriptSig خالی است و امضاها و خود اسکریپت بازخرید در witness میآیند.
نکتهٔ امنیتی: P2SH از هش ۲۰ بایتی RIPEMD160(SHA256(script)) (حدود ۸۰ بیت مقاومت در برابر برخورد) استفاده میکند ولی P2WSH از ۳۲ بایت SHA256 (۱۲۸ بیت). این اختلاف عمدی است: طول هش تفاوت دو نوع witness program را مشخص میکند و امنیت P2WSH را بالاتر میبرد.
تفکیک P2WPKH از P2WSH
هر دو «یک بایت نسخه + یک هش» هستند؛ تنها فرق طول هش است: ۲۰ بایت = P2WPKH (کلید عمومی)، ۳۲ بایت = P2WSH (اسکریپت). کیف پول از همین طول میفهمد.
۵. ارتقا به سگویت
ارتقا دومرحلهای است: ابتدا کیفها خروجی نوع سگویت میسازند، سپس کیفهای آگاه آن را خرج میکنند. برای پرداخت مستقیم P2WPKH/P2WSH، هم فرستنده و هم گیرنده باید ارتقا یافته باشند و فرستنده باید بداند گیرنده سگویتآگاه است؛ وگرنه کیف قدیمی گیرنده پرداخت را نمیبیند. ارتقا همزمان در کل شبکه نیست و P2PKH/P2SH سنتی برای کیفهای ارتقانیافته ادامه میدهند. دو سناریوی باقی: فرستندهٔ غیرسگویتی به گیرندهٔ سگویتی، و فرستندهٔ سگویتی که باید گیرندهٔ آگاه را از ناآگاه تشخیص دهد.
۶. سگویت درون P2SH
راهحل: کیف گیرنده witness program را داخل یک آدرس P2SH (با پیشوند 3) میگذارد؛ کیف قدیمی فرستنده آن را آدرس معمولی میبیند و میفرستد، و گیرنده با تراکنش سگویت خرجش میکند و کارمزد کمتری میپردازد.
- P2SH(P2WPKH): برنامهٔ
0 <hash20>ابتدا SHA256 سپس RIPEMD160 میشود و هش ۲۰ بایتی جدید در اسکریپتHASH160 <h> EQUALمینشیند و آدرس P2SH ساخته میشود (در کتاب:37Lx99…). - P2SH(P2WSH): همان برای
0 <hash32>چندامضایی (در کتاب:3Dwz1M…). بدینترتیب هر مشتری، سگویتی یا غیرسگویتی، میتواند به شرکت پرداخت کند.
۷. آدرسهای سگویت
کتاب میگوید احتمالاً در ماههای اولیه سگویت عمدتاً درون P2SH خواهد بود؛ سپس باید قالب آدرسی ساخته شود که مستقیم witness program را رمز کند و گیرندهٔ سگویتآگاه را مشخص کند. در زمان نگارش چند پیشنهاد بود و هیچکدام فعالانه دنبال نمیشد (بعدها Bech32/BIP-173 آمد).
۸. شناسههای تراکنش: txid و wtxid
- txid: double-SHA256 تراکنش بدون شاهد، دقیقاً مانند قبل.
- wtxid: double-SHA256 قالب جدید سریالسازی همراه شاهد. اگر تراکنش بیشاهد منتقل شود دو شناسه برابرند.
چون در ورودیهای سگویت scriptSig خالی است، بخشی که شخص ثالث بتواند تغییرش دهد باقی نمیماند؛ پس txid حتی برای تراکنش تأییدنشده تغییرناپذیر است — به شرط آنکه همهٔ ورودیها سگویت باشند. wtxid تا زمان تأیید شدن هنوز قابل دستکاری فرض میشود. (خلاصه: تراکنشی که همهٔ ورودیهایش سگویت است، در برابر malleability شخص ثالث مصون است.)
۹. الگوریتم امضای جدید (BIP-143)
سگویت چهار تابع CHECKSIG، CHECKSIGVERIFY، CHECKMULTISIG و CHECKMULTISIGVERIFY را برای نسخهٔ ۰ تغییر میدهد تا «هش تعهد» (commitment hash) متفاوت محاسبه شود. در روش قدیم، یک تراکنش با تعداد زیاد عملیات امضا میتوانست گرهها را به صدها یا هزاران عملیات هش مجبور کند (O(n²))؛ الگوریتم جدید رشد را خطی (O(n)) میکند و دو هدف را میگیرد: کاهش سطح حملهٔ DoS و گنجاندن مبلغ ورودیها در تعهد برای سادهکردن ارتباط میزبان با کیف پول سختافزاری (بدون نیاز به ارسال تراکنشهای قبلی).
۱۰. انگیزههای اقتصادی
کارمزد برحسب اندازه (بایت) محاسبه میشد و همهٔ دادهٔ تراکنش را همارزش میدانست، در حالی که هزینهٔ واقعی برای گرهها متفاوت است. هر تراکنش چهار منبع مصرف میکند:
| منبع | اثر |
|---|---|
| فضای دیسک | ذخیره در بلاکچین (با pruning کم میشود) |
| CPU | اعتبارسنجی |
| پهنای باند | حداقل یکبار پخش + یکبار در بلوک |
| حافظه (RAM) | نگهداری مجموعهٔ UTXO؛ حافظه دستکم ده برابر دیسک گرانتر است |
گرانترین بخش تراکنش خروجیهای تازه است (وارد UTXO set در حافظه میشوند) و ارزانترین، امضا/شاهد است (یکبار بررسی و سپس قابل دورریختن). با کارمزد صرفاً بر پایهٔ اندازه، انگیزه برعکس است و کیفها را به کمترین ورودی ممکن سوق میدهد که میتواند UTXO set را متورم کند. کتاب معیار Net-new-UTXO (خروجیها منهای ورودیها) را تعریف میکند: مثبت یعنی بار بیشتر روی شبکه، منفی یعنی کاهش آن.
مثال کتاب با multisig ۲-از-۳، ۳۰ ساتوشی بر بایت و تخفیف ۷۵٪ روی شاهد:
| تراکنش | Net-new-UTXO | کارمزد بدون سگویت | با سگویت |
|---|---|---|---|
| A (۳ ورودی، ۲ خروجی) | ۱− | ۲۵٬۷۱۰ ساتوشی | ۸٬۱۳۰ |
| B (۲ ورودی، ۳ خروجی) | ۱+ | ۱۸٬۹۹۰ | ۱۲٬۰۴۵ |
بدون سگویت تراکنش A (که UTXO را کم میکند) گرانتر است؛ با سگویت ترتیب برعکس میشود و کارمزد با هزینهٔ واقعی همراستا میشود. نتیجه: سگویت (۱) هزینهٔ کلی تراکنش را با تخفیف شاهد پایین میآورد و ظرفیت زنجیره را بالا میبرد، (۲) ناهمترازی انگیزهای را اصلاح میکند که ناخواسته UTXO را متورم میکرد.
وزن (weight) و vbytes — توضیح تکمیلی
متن این پیوست فقط «تخفیف ۷۵٪ روی شاهد» را میگوید؛ سازوکار اجرایی آن در BIP-141 (توضیح تکمیلی، خارج از متن پیوست): اندازهٔ تراکنش با weight سنجیده میشود؛ بایتهای غیرشاهد ۴ واحد و بایتهای شاهد ۱ واحد وزن دارند، vsize (بایت مجازی) = وزن ÷ ۴ و سقف هر بلوک ۴٬۰۰۰٬۰۰۰ واحد وزن است (حدود ۱ مگابایت غیرشاهد تا حداکثر نظری چند مگابایت با شاهد زیاد). کارمزد معمولاً بر حسب ساتوشی بر vbyte بیان میشود.
جمعبندی
سگویت شاهد را از بدنهٔ تراکنش جدا میکند و با آن malleability شخص ثالث را برطرف، نسخهبندی اسکریپت را ممکن، پیچیدگی هش امضا را از O(n²) به O(n) تبدیل، امضای آفلاین را ساده و کارمزد را با هزینهٔ واقعی شبکه همراستا میکند. بهعنوان سافتفورک، خروجیهای آن برای گرههای قدیمی «قابل خرج با هر امضایی» دیده میشوند و با P2SH-wrapped برای کیفهای قدیمی هم قابل پرداختاند. تفاوت P2WPKH (۲۰ بایت) و P2WSH (۳۲ بایت) و دوگانگی txid/wtxid نکات کلیدی عملی آن است.
پیوست E — Bitcore
Bitcore مجموعهابزاری از شرکت BitPay برای سادهکردن کار توسعهدهندگان بیتکوین است. بیشتر کدش جاوااسکریپت است، بعضی ماژولها مخصوص NodeJSاند و ماژول node کد C++ بیتکوین کور را هم در خود دارد. سایت: bitcore.io.
ماژولها
| ماژول | کار |
|---|---|
bitcore-node |
گره کامل بیتکوین؛ یکپارچهسازی سرویسها مستقیم با Bitcoin Core |
insight |
بلاک اکسپلورر |
bitcore-lib |
ابزار بلاک، تراکنش و کیف پول |
bitcore-p2p |
ارتباط مستقیم با شبکهٔ P2P |
bitcore-mnemonic |
تولید seed بهصورت عبارت یادآور |
bitcore-payment-protocol |
پروتکل پرداخت |
bitcore-message |
امضا و راستیآزمایی پیام |
bitcore-ecies |
رمزنگاری Elliptic Curve Integrated Encryption Scheme |
bitcore-wallet-service / bitcore-wallet-client |
سرویس و کلاینت کیف پول |
bitcore-playground |
محیط آزمایشی آنلاین |
پیشنیاز و نمونهها
نیاز: NodeJS نسخهٔ ۴ یا بالاتر (یا playground آنلاین). نصب: npm install -g bitcore-lib bitcore-p2p و اجرای node با NODE_PATH مناسب.
نمونههای کیف پول با bitcore-lib:
- کلید و آدرس جدید:
new bitcore.PrivateKey()و سپس.toAddress().toString(). - کلید HD:
bitcore.HDPrivateKey()و ساختHDPublicKeyو آدرس از آن. - ساخت و امضای تراکنش از یک UTXO: شیء utxo شامل
txId،outputIndex،address،script(باScript.buildPublicKeyHashOut) وsatoshisساخته میشود؛ سپس زنجیرهایnew Transaction().from(utxo).to(address, 35000).fee(fee).enableRBF().sign(privateKey)تراکنش را میسازد (کارمزد مثال ۳۰۰۰ ساتوشی). - جایگزینی با کارمزد (RBF): تراکنش دوم با همان ورودی و کارمزد دوبرابر ساخته میشود تا تراکنش اول در mempool را جایگزین کند؛ هر دو با
serialize()به رشتهٔ هگز تبدیل میشوند. - پخش در شبکه: اسکریپت
broadcast.jsباbitcore-p2pبه یک همتا (پورت TCP 8333) وصل میشود و پیامTransactionرا برای هر دو تراکنش با فاصلهٔ ۲ ثانیه میفرستد. فقط تراکنش معتبر پخش شود، و برای RBF همتا باید گزینهٔmempoolreplace=1بیتکویندی را فعال کرده باشد.
جمعبندی
Bitcore برای نمونهسازی سریع با جاوااسکریپت مناسب است: تولید کلید و آدرس، HD، ساخت/امضای تراکنش و پخش P2P با چند خط کد.
پیوست F — pycoin، ku و tx
pycoin کتابخانهٔ پایتون (نویسنده و نگهدارندهٔ اولیه: Richard Kiss) برای کار با کلیدها و تراکنشهای بیتکوین است و حتی زبان اسکریپت را به قدری میفهمد که تراکنشهای غیراستاندارد را هم پردازش کند. با Python 2.7 و Python 3 (از 3.3) کار میکند و دو ابزار خط فرمان دارد: ku و tx.
ابزار کلید ku (Key Utility)
«چاقوی سوئیسی» کلیدها: کلیدهای BIP-32، WIF و آدرس (بیتکوین و آلتکوینها). خروجی کامل هر کلید شامل شبکه، کلید کیف (xprv/xpub)، عمق درخت، fingerprint، chain code، secret exponent، WIF (فشرده/فشردهنشده)، مختصات x و y، فرمت SEC، hash160 و آدرس است.
| کار | فرمان |
|---|---|
ساخت کلید BIP-32 با منبع آنتروپی پیشفرض (GPG و /dev/random) |
ku create |
| ساخت کلید از عبارت (فقط مثال؛ عبارت ساده بسیار ناامن است) | ku P:foo |
| خروجی JSON | ku P:foo -P -j |
| نسخهٔ عمومی کلید BIP-32 | ku -w -P P:foo |
| زیرکلید مسیر 3/2 | ku -w -s3/2 P:foo |
| زیرکلید سختشده (hardened) | ku -w -s3/2H P:foo |
| فقط WIF / فقط آدرس | ku -W P:foo / ku -a P:foo |
| دستهای از زیرکلیدها (0/0 تا 0/5) و آدرس/WIF متناظر | ku P:foo -s 0/0-5 -w (و -a, -W) |
| از secret exponent برابر ۱ | ku 1 |
| شبکهٔ دیگر: Litecoin / Dogecoin / testnet | -nL, -nD, -nT |
| از جفت عمومی (x,parity) روی testnet | ku -nT <x>,even |
| از hash160 به آدرس | ku <hash160> (و -nD برای Dogecoin) |
نکات: کتاب با تبدیل رشتهٔ BIP-32 زیرکلید 0/3 به WIF و آدرس نشان میدهد نتایج با فهرست قبلی یکی است (هماهنگی مشتقسازی). مثال secret exponent=1 همان نقطهٔ مولد G است. اضافه میکند که یک hash160 واحد بسته به شبکه آدرس متفاوتی میدهد.
ابزار تراکنش tx (Transaction Utility)
نمایش تراکنش به شکل خوانا، گرفتن تراکنش پایه از حافظهٔ نهان pycoin یا سرویسهای وب (در آن زمان blockchain.info و biteasy.com)، ادغام تراکنشها، افزودن/حذف ورودی و خروجی و امضا.
- پیشنیاز: باید
PYCOIN_CACHE_DIRوPYCOIN_SERVICE_PROVIDERSرا export کرد. عمداً خودکار نیست تا ابزار خط فرمان اطلاعات خصوصی دربارهٔ تراکنشهای مورد علاقهٔ شما را به وبسایت ثالث لو ندهد. - تراکنش «پیتزا»:
tx 49d2adb6…نسخه، تعداد ورودی/خروجی، lock time (=0، همیشه معتبر)، خروجی (۱۰ میلیون mBTC) و dump هگز را نشان میدهد. بدون-aهشدار میدهد نمیتواند اعتبارسنجی کند چون تراکنشهای منبع موجود نیست. - گزینهٔ
-a: تراکنش را با اطلاعات منبع تقویت میکند و میگویدsig okاست، کارمزد صفر و «همهٔ مقادیر ورودی تأیید شد». هشدار میدهد کارمزد کمتر از حد تخمینی است و ممکن است منتشر نشود. fetch_unspent <address>: UTXOهای یک آدرس را به قالبtxid/index/script/amountفهرست میکند (مثال: آدرس coinbase بلوک ۱).
جمعبندی
ku برای آزمایش کلید و آدرس (BIP-32، WIF، شبکههای مختلف) و tx برای بررسی و ساخت/امضای تراکنشها مناسباند؛ هر دو برای یادگیری و دیباگ، نه نگهداری کلید واقعی با عبارتهای ساده.
پیوست G — دستورات Bitcoin Explorer (bx)
Bitcoin Explorer (bx) ابزار خط فرمان برای مدیریت کلید و ساخت تراکنش است و بخشی از کتابخانهٔ libbitcoin. شکل کلی: bx COMMAND [--help]. دستورها با pipe و redirect ترکیب میشوند (ورودی از stdin، خروجی در stdout).
گروههای دستور
| گروه | دستورها | کار |
|---|---|---|
| آدرس | address-decode, address-embed, address-encode, address-validate |
رمزگشایی/ساخت/اعتبارسنجی آدرس، جاسازی داده |
| رمزگذاری | base16-*, base58-*, base58check-*, base64-*, wrap-* |
تبدیل بین قالبها (hex, Base58, Base58Check, Base64) |
| هش | bitcoin160, bitcoin256, ripemd160, sha160, sha256, sha512 |
توابع هش |
| واحد | btc-to-satoshi, satoshi-to-btc |
تبدیل واحد |
| منحنی بیضوی | ec-new, ec-to-public, ec-to-address, ec-to-wif, ec-add, ec-add-secrets, ec-multiply, ec-multiply-secrets, wif-to-ec, wif-to-public |
کلید خصوصی/عمومی، WIF، جمع و ضرب |
| کلید HD | hd-new, hd-private, hd-public, hd-to-address, hd-to-ec, hd-to-public, hd-to-wif |
مشتقسازی BIP-32 |
| mnemonic و seed | seed, mnemonic-encode, mnemonic-decode |
تولید seed و عبارت یادآور |
| تراکنش و اسکریپت | tx-encode, tx-decode, input-set, input-sign, input-validate, script-encode, script-decode, script-to-address, validate-tx |
ساخت، امضا و بررسی تراکنش |
| شبکه | fetch-balance, fetch-header, fetch-height, fetch-history, fetch-stealth, fetch-tx, fetch-tx-index, send-tx, send-tx-node, send-tx-p2p, watch-address |
پرسوجو و ارسال |
| پیام | message-sign, message-validate |
امضای پیام |
| آدرس پنهان | stealth-* |
stealth address |
| سایر | uri-encode/decode, settings, help |
URI، تنظیمات |
مثالها
کلید نامعین (nondeterministic، نوع ۰): هر کلید از seed مستقل میآید:
bx seed | bx ec-new > private_key
bx ec-to-public < private_key > public_key
bx ec-to-address < public_key
seed از مولد تصادفی سیستمعامل استفاده میکند؛ ec-new کلید خصوصی میسازد؛ ec-to-public کلید عمومی فشردهٔ ۳۳ بایتی؛ ec-to-address آدرس.
کیف پول قطعی (HD، BIP-32، نوع ۲):
bx seed > seed
bx hd-new < seed > master
bx hd-private --hard < master > account
bx hd-private --index 0 < account
bx hd-public --index 0 < account
کلید master از seed ساخته میشود؛ --hard کلید «حساب» سختشده میسازد؛ با --index زیرکلیدهای خصوصی/عمومی مشتق میشوند. hd-to-public از کلید خصوصی HD معادل عمومی را میدهد (نتیجه با hd-public یکی است). مزیت: بینهایت کلید از یک seed که با یک مقدار پشتیبان و بازیابی میشود.
عبارت یادآور: seed با mnemonic-encode (در کتاب hd-mnemonic آمده) به ۱۲ واژه تبدیل میشود و mnemonic-decode آن را برمیگرداند؛ ثبت و حفظ seed آسانتر میشود.
جمعبندی
bx جعبهابزاری ماژولار برای آزمایش مفاهیم کتاب (کلید، آدرس، HD، mnemonic، تراکنش) است؛ مستندات رسمی در صفحهٔ خانگی Bitcoin Explorer موجودند.

