نگارش 25 خرداد 1398
بیتکوین (Bitcoin)، اولین رمزارز (Cryptocurrency) جهان بود که با کنار هم قرار دادن دانشهای پیش از خودش و اضافه کردن الگوریتم اثبات کار (Proof of Work) شکل گرفت. حالا که تصمیم گرفتید از ارزهای دیجیتال بیشتر بدونید، فهمیدن طرز کار شبکهی بیتکوین شروع بسیار خوبی هست. و بعدا میتونید تغییراتی که رمزارزهای دیگه روی این پروتکل ایجاد کردن یا ایدههایی جدیدی که ارائه کردن رو مطالعه و مقایسه کنید.
برای شروع، در ادامه مفاهیمی رو بدون ورود به جزئیات پیادهسازیشون مرور میکنیم. هرجایی که از تابع استفاده شده، شما میتونید جعبهای رو تصور کنید که نمیدونیم داخلش چه اتفاقی میافته؛ اما یک یا چند ورودی رو دریافت و یک یا چند خروجی دیگه تحویل میده.
هش تابعی هست که یک ورودی با طول نامشخص رو میگیره و معمولا خروجی با طول مشخص میده. سعی میشه این تابع به نحوی باشه که امکان تولید خروجی دلخواه امکانپذیر نباشه. یعنی از روی خروجی، ورودی قابل حدس یا محاسبه نباشه. از نظر تئوری، میدونیم که خروجی طول مشخص داره و بنابراین محدود هست. پس ورودیهایی وجود خواهند داشت که خروجی یکسانی داشته باشن. اما تعداد حالات خروجی بسیار زیاد و در عمل پیدا کردن دو ورودی با خروجی یکسان غیر ممکن هست. زمانی که تابع درهمسازی دیگه این خاصیت رو نداشته باشه، غیر امن و منسوخ محسوب شده و برای کاربردهای امنیتی دیگه استفاده نمیشه.
اگر دوست دارید اطلاعات کاملی به دست بیارید، میتونید ویدئوهای هش جادی رو ببینید.
فرض کنید که تصمیم دارید پیامی رو به دوستتون ارسال کنید، بدون اینکه کسی از محتوای این پیام باخبر بشه. ابتدا نیاز هست که یک کلید (Key) تصادفی محرمانه تولید کنید و اون رو در اختیار دوستتون هم قرار بدید. اگر این کلید کاملا تصادفی نباشه و قابل حدس زدن باشه، پس دیگه محرمانه هم محسوب نمیشه و پاسخگوی نیاز ما نیست. حالا بعد از اینکه پیام خودتون رو آماده کردید به کمک الگوریتم رمزنگاری خاصی که کلید رو براش تولید کردید، پیام رو رمزنگاری (Encrypt) میکنید و به هر روش و با هر واسطهی دلخواهی این پیام رو برای دوستتون ارسال میکنید. خیلیها ممکنه پیام رمزنگاری شده توی مسیر رو ببینن ولی اصل پیام رو نمیتونن بازیابی کنن. اما دوستتون با داشتن کلید میتونه پیام رو رمزگشایی (Decrypt) کنه و اون رو بخونه.
رمزنگاری غیر متقارن هم مشابه با حالت متقارن هست با این تفاوت که در این حالت به جای یک کلید، یک جفت کلید تولید میشه: کلید خصوصی (Private Key) و کلید عمومی (Public Key). هرکسی این جفت کلید رو برای خودش تولید میکنه و کلید خصوصی خودش رو به صورت محرمانه ذخیره میکنه و کلید عمومی رو در اختیار همه قرار میده. هر دادهای که با کلید خصوصی رمزنگاری بشه، با کلید عمومی قابل بازگشایی هست و اینطوری دریافتکنندهی پیام میتونه تصدیق کنه این داده حتما توسط شخصی که کلید خصوصی متناظرش رو داره رمزنگاری شده. از طرف دیگه، هر پیامی که با کلید عمومی رمزنگاری بشه فقط توسط کلید خصوصی متناظرش قابل رمزگشایی هست.
ویدئوی رمزنگاری جادی احتمالا برای فهم این بخش هم کمک خوبی باشه.
رمزنگاری و امضا رو که با هم ترکیب کنیم به حالتهای جالبی میرسیم. شما برای ارسال پیام، اون رو با کلید خصوصی خودتون امضا میزنید و با کلید عمومی گیرنده رمزنگاری میکنید و براش ارسالش میکنید. و پیامهای دریافتی رو هم که میتونید با کلید عمومی خودتون رمزگشایی کنید و از روی امضایی که زده شده مطمئن بشید که پیام از شخصی که انتظار دارید یا ادعا شده اومده.
فرض کنید قصد داریم یک پول دیجیتالی بسازیم. کسایی که علاقهمند هستیم دور هم جمع میشیم و از طریق اینترنت اطلاعات رو بین خودمون مخابره میکنیم. هر کسی هر پیامی رو که داشته باشه میتونه برای چند نفر توی شبکهای که ساختیم بفرسته و اونها هم پیام رو به بقیه اعضا میرسونن تا در نهایت همه از اون خبردار بشن.
برای شروع، ۱۰۰ سکه رو برای پیمان در نظر میگیریم و کلید عمومیش رو هم در اختیار همه قرار میدیم. اعضای شبکه هم موافقت میکنن و یادداشتی رو برای خودشون ایجاد میکنن که یک ستون اون کلید عمومی و ستون دیگه میزان موجودی هست. و اولین ردیف رو هم با میزان موجودی کلید عمومی پیمان پر میکنن.
در این شبکه هرکسی که قصد ایجاد حساب جدید داره، فقط کافیه که یک جفت کلید برای خودش تولید کنه و نیازی هم نیست که این رو به کسی اعلام کنه. حالا فرض کنید پیمان قصد داره ۲۰ سکه برای کامران ارسال کنه. کامران یک جفت کلید تولید و کلید عمومی اون رو در اختیار پیمان قرار میده. پیمان مطابق با قوانین شبکهای که ساختیم، مینویسه که مثلا در این تاریخ ۲۰ سکه رو از حسابم برای کامران (در حقیقت کلید عمومیش رو فقط اعلام میکنه و اسمی از کامران برده نمیشه) ارسال کردم و اون رو با کلید خصوصی خودش امضا و در شبکه منتشر میکنه. تمامی افرادی که این پیام میبینن، میتونن احراز کنن که خود پیمان چنین پیامی رو امضا کرده و یادداشتهای خودشون رو بروز میکنن.
حالا در یادداشت (دفتر کل) اعضا نوشته شده که کلید عمومی پیمان ۸۰ سکه و کلید عمومی کامران ۲۰ سکه داره. البته برای اینکه مشکلی به وجود نیاد و یک تراکنش چند بار یا اصلا محاسبه نشه، بهتر هست که تراکنشها رو نگهداری کنیم و هر لحظه برای فهمیدن موجودی تمامی تراکنشها رو از ابتدا تا انتها مرور کنیم.
کامران که حالا مقداری سکه داره، تصمیم میگیره اون رو در اختیار حسن قرار بده و ازش یک کالایی رو خریداری کنه. پس تراکنش امضا شده رو به حسن میده و حسن هم کالا رو در اختیارش قرار میده چون مطمئن هست که این کلید عمومی موجودی کافی رو داره و امضا هم توسط دارنده اون زده شده و این برای همهی اعضا قابل قبول هست.
در همین حین کامران کنجکاو میشه شبکهای که ساختیم رو کمی به چالش بکشه و تصمیم میگیره از علی هم کالای دیگهای رو با همین قیمت خریداری کنه. دوباره روند قبلی رو انجام میده و اینبار امضا میکنه که موجودی من به علی انتقال پیدا کنه. علی هم چون هنوز از تراکنشی که باهاش سکهها باید به حسن انتقال پیدا میکرده خبردار نشده (به دلیل همزمان بودن تراکنشها یا کامل انتشار پیدا نکردن تراکنش قبلی)، کالا رو به کامران میده.
حالا این دو تراکنش در شبکه منتشر میشن و اعضا احتمالا اولین تراکنشی که به دستشون رسیده رو در دفتر کلهای خودشون اعمال میکنن. زمانی که دومین تراکنش به دستشون میرسه، میتونن تصدیق کنن کامران یا هرکسی که کلید خصوصیش رو داشته چنین تراکنشی رو امضا کرده. ولی میدونن کامران موجودی کافی برای دومین تراکنش رو نداره و نمیتونن اون رو در دفتر کلشون اعمال کنن. این کار باعث ایجاد دو دستگی در بین اعضای شبکه میشه و شبکهای که ساختیم اعتبار خودش رو برای همیشه از دست میده. به کاری که کامران انجام داد اصطلاحا «دو بار خرج کردن» (Double Spending) گفته میشه.
تمام مطالبی که تا اینجای کار گفتیم از دهههای قبل هم وجود داشت و مهمترین کاری که بیتکوین انجام داد، حل کردن مشکل دو بار خرج کردن با استفاده از الگوریتم اثبات کار (Proof of Work) بود. که به طبع اون مفهوم استخراج (Mining) به وجود اومد.
همون شبکهی قبل رو در نظر بگیرید اما اینبار فرض کنید تراکنشهایی که به صورت تکی در شبکه منتشر میشه باید در داخل یک جعبه یا بلوک (Block) هم قرار بگیرن و مسئلهای براشون حل بشه تا معتبر شناخته بشن. بعدش بلوکی که جوابش پیدا شده در شبکه منتشر میشه تا همه ازش با خبر بشن و دیگه بلوکی با تراکنشهایی که تایید شده درست نکنن.
خب کمی به بیتکوین نزدیکتر بشیم و با مفاهیم اون پیش بریم. برای اینکه معدنچیها (Minerها) تشویق بشن جواب مسائل رو پیدا کنن، جایزهای براشون در هر بلوک در نظر گرفته میشه. همینطور اونها میتونن کارمزدهایی که امضا کنندهها برای هر تراکنش در نظر گرفتن رو برای خودشون بردارن.
چه چیزهایی در هر بلوک قرار میگیره؟ معدنچیها اول از همه باید آدرس خودشون رو در بلوک قرار بدن تا مشخص بشه جایزهی حل مسئله قرار هست به چه کسی تعلق پیدا کنه. هر بلوک به بلوک قبلی خودش هم اشاره میکنه تا ترتیب بلوکها مشخص باشه؛ اینطوری با داشتن آخرین بلوک میتونیم تا اولین بلوک پیش بریم و همهی تراکنشهای شبکه رو مرور کنیم. در این تراکنشها نباید تناقض یا عدم سازگاری وجود داشته باشه. و مهمترین بخش قضیه تراکنشها هست که معدنچی اونها رو طوری انتخاب میکنه تا بیشترین کارمزد نصیبش بشه. مطابق قوانین شبکه، حجم بلوکها محدود هست و وقتی تراکنشها بیشتر از ظرفیت بلوک هستن فقط بخشی از اونها رو میشه داخلش جا داد. و چند تا چیز دیگه هم داخل بلوک قرار میگیره، به علاوهی یک دادهی دلخواه که در ادامه توضیح میدم به چه دردی میخوره.
به این بلوکها که به صورت زنجیرهای به هم متصل هستند، زنجیره بلوکها یا بلاکچین (Blockchain) گفته میشه.
مسئلهای که باید حل بشه چیه؟ وقتی معدنچی به صورت موقت بلوکی رو میسازه، باید تابع درهمسازی (hash) رو روی اون اعمال کنه. به این ترتیب یک خروجی با طول ثابت مثلا ۶۴ کاراکتری به دست میاد. جواب مسئله اینه که باید تعداد مشخصی از کاراکترهای ابتدایی صفر باشن. (در عمل باید کوچکتر از عدد مشخصی باشه اما همین حالتی که مطرح شد تفاوت زیادی نداره) مسئله قابل محاسبه نیست و فقط با امتحان کردن ورودیهای مختلف میشه به جوابش رسید. پس معدنچی هر مرتبه دادهی دلخواهی رو که گفتیم تغییر میده (مثلا از صفر شروع میکنه و هر مرتبه یکی اون رو زیاد میکنه) تا به جواب مسئله برسه.
حل کردن این مسئله چقدر سخت هست؟ سختی مسئله بستگی به این داره تعداد صفرهایی که در ابتدا قرار میگیره چند تا باید باشه. مثلا اگر هر کاراکتر ۱۶ حالت داشته باشه و ما بخوایم فقط کاراکتر اول خروجی صفر باشه، این مسئله مشابه با یک تاس ۱۶ وجهی هست که ما میخوایم وجه صفر اون بیاد. کار خیلی سختی نیست و اگه صد بار انجام بدیم احتمالش خیلی زیاد هست که خروجی صفر رو در یکی از اونها داشته باشیم. دقت کنید که این قضیه کاملا شانسی هست و ممکنه مرتبه اول شما خروجی صفر بگیرید و ممکنه بعد صد بار هم حتی موفق نشید هرچند احتمالش کم هست. حالا فرض کنید دو کاراکتر اول خروجی بخوایم صفر باشه. این مسئله مشابه با این حالت هست که دو تاس ۱۶ وجهی رو بخوایم همزمان پرتاب کنیم و هر دو باید صفر بشن. کمی سختتر شد. و اگر تعداد صفرهای ابتدایی خروجی باید بیشتر باشند، این مسئله به صورت تصاعدی سختتر میشه.
صفرها چند تا هستن؟ معدنچیها یا ماینرها میلیونها میلیون بار در هر ثانیه این ورودی رو تغییر میدن و هش بلوک رو محاسبه میکنن تا به جواب برسن. با این حال به طور متوسط ۱۰ دقیقه طول میکشه تا فقط یکیشون بتونه جواب مسئله رو پیدا کنه. تعداد صفرها مطابق با قوانین شبکه طوری تعیین میشه که عدد طلایی متوسط ۱۰ دقیقه حفظ بشه. یعنی اگر تعداد کسایی که به دنبال جواب میگردن یا قدرت محاسباتی اونها افزایش پیدا کنه، جوابها برای مدتی سریعتر پیدا میشن ولی سختی استخراج (Mining Difficulty) هم به طبع اون افزایش پیدا میکنه تا دوباره ایجاد هر بلوک زمان بیشتری لازم داشته باشه. بالطبع در ابتدای راهاندازی شبکه که قدرت محاسباتی اعضا کم هست، مسئله سادهتره و وقتی که قدرت محاسباتی بیشتر شد مسئله سختتر و سختتر میشه.
استخراج چه منفعتی برای شبکه داره؟ مثال کامران رو به یاد بیارید که همهی پولش رو هم به حسن و هم به علی انتقال داده بود. بدون وجود بلوکهایی که براشون انرژی زیادی مصرف میشه تا مورد تایید قرار بگیرن، دو دستگی بین اعضای شبکه به وجود اومده بود. اما حالا معیاری برای تشخیص تراکنش تایید شده و تراکنش رد شده وجود داره. فرض کنید معدنچی که جواب مسئله رو پیدا میکنه، تراکنش حسن رو در بلوک خودش قرار داده بوده. وقتی که این بلوک در شبکه منتشر میشه، همه متوجه میشن که تراکنش انتقال وجه به حسن مورد پذیرش قرار گرفته و روی اون توافق میکنن. و در ادامه تلاش میکنن بلوکهای جدید رو در امتداد آخرین بلوک تایید شده بسازن.
علی که از این وضعیت ناراحت هست، تصمیم میگیره خودش به عنوان معدنچی یا با کمک گرفتن از بقیه معدنچیها بلوکی رو تشکیل بده که در اون تراکنشی که سکهها به خودش انتقال پیدا میکنه قرار داره. اگر علی و دوستان معدنچیش قدرت محاسباتی زیادی داشته باشند، میتونن این کار رو انجام بدن. اما باید دید که صرف این همه انرژی برای اونها اقتصادی هست یا نه. گفتیم که بلوکها در امتداد هم تشکیل میشن. و اگر بلوکهای جدیدی در ادامهی بلوکی که درش سکهها به حسن انتقال پیدا میکنه تشکیل شده باشه، علی باید انرژی خیلی بیشتری رو هم صرف کنه و قبل از جایی که سکهها به حسن میرسه، شاخهای (Fork) رو جدا کنه که در بلوک پس از اون سکهها به خودش میرسه و چند بلوک در امتداد اون هم بسازه. چون اعضای شبکه شاخهای رو قبول میکنن که بیشترین تعداد بلوک (در واقع بیشترین انرژی صرف شده) رو داشته باشه و این کارش رو سختتر میکنه.
پس در شبکهی بیتکوین وقتی خیالمون راحت میشه تراکنش برگشتپذیر نیست که مطمئن باشیم اولا در یک بلوک حل شده قرار گرفته و دوما به تعداد کافی بلوک در امتداد اون تشکیل شده که بسته به مبلغ دریافتی، کسی براش اقتصادی نیست که تلاش کنه تراکنش جایگزینی رو معتبر کنه که در اون سکهها به جای رسیدن به ما، به کیف پول خودش برمیگرده.