علوم کامپیوتر
بلاکچین چطور کار میکند؟ یک زنجیرهٔ کوچک با پایتون بساز
بلوک، هش قبلی، دستکاری، اجماع و proof of work را با کد قابل اجرا بفهم. چرا یک لیست از هشها هنوز بیتکوین نیست؟

تصویر اختصاصی مجلهٔ ساروی؛ ساختهشده با هوش مصنوعی
سه رکورد ساختگی را به هم وصل میکنیم، یکی را عوض میکنیم و میبینیم کدام آزمون خطا را پیدا میکند. سپس کل زنجیره را دوباره میسازیم؛ این بار آزمون ساده قبولش میکند. همین شکست، نیاز به مرجع قابل اعتماد و اجماع را روشن میکند.
این کار را در ساروی شروع کن۱. بلوک ما سه فیلد دارد
index جای رکورد در زنجیره است، data یک متن ساختگی و previous_hash اثر انگشت بلوک قبلی. بلوک اول به جای قبلی، ۶۴ صفر میگذارد. این انتخاب فقط قرارداد نمونهٔ ماست.
عبارت «A sends B 10» صرفاً متن است. کد نه موجودی را میفهمد، نه مالکیت را بررسی میکند و نه جلوی خرج دوباره را میگیرد. اگر متن را با «A sends B 999» عوض کنیم، تابع هش باز هم یک خروجی معتبر میسازد.
@dataclass(frozen=True)
class Block:
index: int
data: str
previous_hash: str
def append(chain, data):
previous = digest(chain[-1]) if chain else "0" * 64
chain.append(Block(len(chain), data, previous))۲. نمایش داده قبل از هش باید مشخص باشد
اگر دیکشنری را با فاصلهها یا ترتیب متفاوت به متن تبدیل کنی، بایتها و هش عوض میشوند. در نمونه، کلیدها مرتب میشوند، جداکنندهها ثابتاند و UTF-8 استفاده میشود. این قرارداد محلی برای همین کد پایتون است؛ قالب اجماع میان چند زبان را باید دقیقتر تعریف کرد.
frozen=True جلوی تغییر معمول فیلدها را میگیرد، اما تضمین امنیت شبکه نیست. برای ساخت نسخهٔ تغییرکرده از replace استفاده میکنیم. کد کامل قابل دانلود است و فقط کتابخانهٔ استاندارد میخواهد.
def digest(block):
payload = json.dumps(
{"index": block.index, "data": block.data,
"previous_hash": block.previous_hash},
sort_keys=True, separators=(",", ":"), ensure_ascii=False,
).encode("utf-8")
return sha256(payload).hexdigest()۳. لینکها را قدمبهقدم بررسی کن
از صفرها شروع میکنیم. index هر بلوک باید با جای واقعی آن برابر باشد. previous_hash آن هم باید با هش بلوک قبلی یکی باشد. بعد، هش بلوک فعلی را برای دور بعد نگه میداریم.
اگر دادهٔ بلوک اول تغییر کند و بلوک دوم ثابت بماند، لینک دوم دیگر به هش جدید اشاره نمیکند. valid مقدار False میدهد. زنجیرهٔ هش برای آشکار کردن بعضی تغییرها مفید است.
def valid(chain):
previous = "0" * 64
for index, block in enumerate(chain):
if block.index != index or block.previous_hash != previous:
return False
previous = digest(block)
return True۴. دو تغییری که تابع ما قبول میکند
اول، فقط متن آخرین بلوک را عوض کن. بلوک بعدی وجود ندارد که به هش قبلی آن اشاره کند؛ تابع لینکها به تنهایی این تغییر را پیدا نمیکند. اگر هش نهایی اصلی را از مرجع قابل اعتماد نگه داشته باشی، مقایسهٔ آن اختلاف را آشکار میکند.
دوم، از ابتدا زنجیرهٔ جدیدی با دادهٔ تغییرکرده بساز. همهٔ previous_hashها هماهنگاند و valid آن را قبول میکند. پس «هش قبلی دارد» به تنهایی به معنی «هیچکس نمیتواند تاریخچه را عوض کند» نیست. فایل دانلودی این دو حالت را تست میکند.
۵. اجماع کدام مسئله را اضافه میکند؟
شرکتکنندههای شبکه ممکن است نسخههای متفاوتی از تاریخچه ببینند. باید روشن شود چه رکوردی معتبر است، ترتیب آن چیست و با رقابت تاریخچهها چه میکنیم. الگوریتم اجماع و فرضهای امنیتی شبکه به این پرسشها مربوطاند.
در طرح بیتکوین، امضای تراکنش، proof of work و قواعد اعتبارسنجی کنار هم قرار میگیرند. مقالهٔ اصلی، زنجیرهٔ مبتنی بر کار انباشته را در شرایط خودش توضیح میدهد. این به معنی «هر زنجیرهٔ بلندتر معتبر است» نیست؛ بلوکها و تراکنشها باید قواعد شبکه را هم رعایت کنند. مقالهٔ بیتکوین
۶. proof of work را تصور کن
فرض کن باید عددی به نام nonce پیدا کنی تا هش داده به یک الگوی سخت برسد. بررسی جواب آسان است، اما پیدا کردن آن نیازمند تلاشهای زیاد میشود. با تغییر داده، جستوجوی مناسب آن داده باید دوباره انجام شود.
این توضیح برای درک تفاوت هزینهٔ ساختن و بررسی است. شبکهٔ واقعی هدف عددی، تنظیم سختی و قواعد دقیق دارد. در این تمرین mining یا پرداخت نداریم؛ هدف، اجرای سبک و دیدن محدودیت زنجیرهٔ محلی است.
۷. اجرا و سه تمرین
با Python 3 فایل toy_chain.py را اجرا کن. all checks passed یعنی هم تغییرهایی که باید رد شوند بررسی شدهاند و هم ضعفهای آگاهانهٔ نمونه ثبت شدهاند. قبول شدن تست، برنامه را به دفترکل امن تبدیل نمیکند.
تمرین اول: حذف بلوک از وسط را تست کن. دوم: با نگه داشتن trusted_tip تابع مقایسهٔ هش نهایی اضافه کن. سوم: نیازهای یک سامانهٔ چندکاربره را بنویس؛ امضا، قوانین تراکنش، اجماع و انتقال پیام در آن باشند.
python3 toy_chain.py
# Toy chain: all checks passed۸. از ساروی بخواه طراحی را نقد کند
«بلاکچین بساز» معمولاً یک کلاس Block و چند هش میدهد. سؤال بهتر: «چه تغییرهایی از این اعتبارسنج رد میشوند و چه تغییرهایی عبور میکنند؟ برای هر ادعا تست بساز.» این روش به محدودیت واقعی کد میرسد.
برای پایهٔ مفهومی، هش و رمزگذاری را بخوان. اگر فایل و دیکشنری دشوارند، پایتون از صفر نقطهٔ شروع بهتری است.
این کار را خودت انجام بده.
- تست تغییر بلوک وسط و آخر را اجرا کن.
- تفاوت لینک معتبر و تاریخچهٔ قابل اعتماد را توضیح بده.
- یک تست برای حذف بلوک از وسط اضافه کن.
برای بررسی بیشتر
Bitcoin: مقالهٔ اصلیPython hashlibدر انجام این کار به مشکل خوردی؟
از پشتیبانی کمک بگیر