توضیحنامهی ۰۳
راستیآزمایی روی زنجیره: ۲۵۶ بایت و یک جفتسازی چه میخرند
معما
قرارداد هوشمندی که آرای ما را میپذیرد روی راریمو L2 زندگی میکند. باید در یک تراکنش واحد تصمیم بگیرد آیا یک کاربر:
- یک گذرنامهی ایرانی یا INID واقعی دارد،
- قبلن به این پیشنهاد رای نداده،
- بهاندازهی کافی سن دارد و شهروند ایران است،
…همهی اینها بدون اینکه هرگز سند را ببیند.
رویکرد سادهانگارانه — بازمحاسبهی کل بررسی امضای گذرنامه درون قرارداد هوشمند — ناممکن است. این کار نیاز به اجرای میلیونها عمل حسابی روی زنجیره دارد، با هزینهی صدها دلار به ازای هر رای.
بهجای آن، قرارداد یک بررسی کوچک انجام میدهد که جایگزین کل محاسبه میشود. آن بررسی کوچک همان چیزی است که هویت ZK را عملی میکند.
کاربر چه چیزی آپلود میکند
تلفن کار سنگین را انجام میدهد. سه چیز تولید میکند:
| شیء | اندازه | از کجا میآید |
|---|---|---|
| اثبات | ~ ۲۵۶ بایت | خروجی اثباتگر Groth16 پس از اجرای مدار روی ورودیهای خصوصی |
| سیگنالهای عمومی | ~ ۲۴ عدد، ~ ۷۶۸ بایت | خروجیهای اعلامشدهی مدار: nullifier، ریشهی ICAO، شناسهی رویداد، تاریخها، تابعیت و غیره |
| شناسهی مدار | یک رشتهی کوتاه | به قرارداد میگوید از کدام کلید راستیآزمایی استفاده کند (passport_rsa_2048_sha256_e65537، inid_rsa_2048، …) |
این تمام چیزی است که زنجیره از کاربر میبیند. نه نام، نه شمارهی گذرنامه، نه امضا. فقط یک اثبات + یک فهرست با اندازهی ثابت از اعداد + یک برچسب.
قرارداد چه میکند — در پنج خط
function verify(circuitID, proof, publicSignals) {
VerifyingKey vk = circuitRegistry[circuitID]; // lookup
require(publicSignals.icaoRoot == currentRoot); // sanity check
require(!nullifierUsed[publicSignals.nullifier]); // anti-replay
require(groth16Verify(vk, proof, publicSignals)); // THE math step
nullifierUsed[publicSignals.nullifier] = true;
}
همه چیز بایگانی است جز خط چهارم. آن خط چهارم همان دلیلی است که هر چیزی در این سیستم کار میکند.
خط چهارم: groth16Verify واقعن چه میکند
یک اثبات Groth16 از سه نقطهی منحنی بیضوی تشکیل شده:
- A روی منحنی G1 (~ ۶۴ بایت)
- B روی منحنی G2 (~ ۱۲۸ بایت)
- C روی منحنی G1 (~ ۶۴ بایت)
کلید راستیآزمایی (یکبار به ازای هر مدار متعهد میشود) به قرارداد میدهد:
- دو نقطهی ثابت α و β
- یک نقطهی ثابت γ
- یک نقطهی ثابت δ
- یک نقطه به ازای هر سیگنال عمومی، با نام IC₀، IC₁، …
قرارداد یک ترکیب خطی روی سیگنالهای عمومی محاسبه میکند:
ICₚ = IC₀ + s₁·IC₁ + s₂·IC₂ + … + sₙ·ICₙ
…و سپس یک معادلهی واحد را بررسی میکند که شامل یک جفتسازی است — یک عمل خاص روی نقاط منحنی بیضوی که با e(·, ·) نوشته میشود:
e(A, B) == e(α, β) · e(ICₚ, γ) · e(C, δ)
اگر این معادله برقرار باشد، اثبات معتبر است. اگر نباشد، نیست. هیچ حالت میانی نیست، و هیچ چیز دیگری برای بررسی نیست.
این تکمعادله از نظر ریاضی معادل با راستیآزمایی هر ضرب و جمع است که اثباتگر ادعا کرده انجام داده. نسبت فشردهسازی شگفتانگیز است: میلیونها قید روی سمت اثباتگر در یک بررسی جفتسازی روی سمت راستیآزما فرومیریزد. این قلب «succinct» در zk-SNARK است.
چرا EVM میتواند این را در میلیثانیه انجام دهد
زنجیرههای سازگار با اتریوم یک نشانی ویژه — 0x08 — دارند که عمل جفتسازی BN254 را در کد بومی انجام میدهد، نه در EVM تفسیری. این یک قرارداد precompiled نامیده میشود. فراخوانی آن مقدار ثابتی gas میخواهد (~ ۱۲۰k برای جفتسازی + ~ ۶k به ازای هر سیگنال عمومی). روی راریمو L2 با ~ ۰٫۰۰۱ دلار به ازای هر تراکنش، این بهخوبی زیر یک سنت به ازای هر راستیآزمایی است.
بدون precompile، راستیآزمایی ZK روی زنجیره از نظر اقتصادی شدنی نبود. راریمو L2، مانند اتریوم و هر L2 مهم، این را دارد. این همان عنصر اولیهای است که میکسرهای سبک tornado، رولآپهای Aztec و زنجیرههای zk-EVM را قدرت میدهد؛ ما در حال استفادهی دوباره از دههها مهندسی رمزنگاری هستیم، نه اختراع آن.
عدمتقارن: اثباتگر در مقابل راستیآزما
اعداد زیر برای مدار ثبتنام ما (~ ۵ میلیون قید) معمولاند:
| گام | کجا اجرا میشود | زمان | هزینه |
|---|---|---|---|
| تولید witness | تلفن (ماژول بومی) | ~ ۲۰–۶۰ ثانیه | باتری |
| تولید اثبات | تلفن (rapidsnark-wrp) | ~ ۳۰–۹۰ ثانیه | باتری |
| فرستادن تراکنش | رله | ~ ۱ ثانیه | ~ ۰٫۰۰۱ دلار gas RMO |
| راستیآزمایی روی زنجیره | قرارداد هوشمند | ~ ۳ میلیثانیه | ~ ۱۲۰k gas |
این عدمتقارن کل هدف است. تلفن کاری متناسب با مدار انجام میدهد (میلیونها عمل)؛ زنجیره کاری با زمان ثابت بدون توجه به پیچیدگی مدار. یک بررسی گذرنامه با ۵ میلیون قید و یک بررسی با ۵ میلیارد قید، هر دو در حدود همان ۳ میلیثانیه راستیآزمایی میشوند.
چرا به ثبت مدار نیاز داریم
یک کلید راستیآزمایی Groth16 فقط برای دقیقن یک مدار کار میکند. اسناد و الگوریتمهای امضای مختلف به مدارهای مختلف نیاز دارند:
| کلاس سند | شناسهی مدار | کلید راستیآزمایی |
|---|---|---|
| گذرنامهی بیومتریک ایرانی (RSA 2048، SHA-256، e=65537) | passport_rsa_2048_sha256_e65537 | vk1.json |
| گذرنامهی بیومتریک ایرانی (RSA 3072، SHA-1، e=58333) | passport_rsa_2048_sha1_e58333 | vk2.json |
| کارت ملی هوشمند ایرانی | inid_rsa_2048 | vk3.json |
| گذرنامهی آلمانی (ECDSA brainpoolP384r1) — برنامهریزیشده | passport_ecdsa_p384_sha384 | (M7) |
هر شناسهی مدار به یک کلید راستیآزمایی متمایز نگاشت میشود. sso-svc ما یک ثبت از این کلیدها نگه میدارد؛ کیف پول به سرویس میگوید از کدام مدار استفاده کرده، و سرویس کلید درست را انتخاب میکند. افزودن یک کلاس سند جدید یک تغییر پیکربندی است، نه تغییر کد.
سیگنالهای عمومی چه چیزی را افشا میکنند — و چه نمیکنند
قرارداد سیگنالهای عمومی را بهعنوان اعداد با موقعیت ثابت میخواند. برای مدار query INID اینها ۲۳ مقدارند؛ برای مدار گذرنامه، ۲۴. نگاشت مشخص برای یک ثبتنام INID:
| اندیس | معنا | حساس؟ |
|---|---|---|
| ۰ | Nullifier (مختص این رویداد) | نه — قابلپیوند به هویت نیست |
| ۵ | شناسهی رویداد (کدام پیشنهاد) | نه — بههرحال عمومی است |
| ۶ | کد تابعیت (مثلن IR) | نه — فقط در سطح کشور |
| ۸ | هش شمارهی شخصی (فقط INID) | نه — هششده؛ هیچ preimage روی زنجیره نیست |
| ۱۰ | زمانمهر تولید هویت | نه — ساعت دیواری |
| ۱۲ | سلکتور (کدام ادعاها منتشر شوند) | نه — طراحانه منتشر میشود |
| ۱۳ | تاریخ فعلی | نه — ساعت دیواری |
| ۲۱ | نتیجهی بررسی تابعیت (ایران؟ بله/خیر) | نه — بولی |
| ۲۲ | ریشهی RegistrationSMT | نه — وضعیت زنجیره |
هیچ فیلدی برای نام، شمارهی سند، هش عکس، تاریخ تولد یا تاریخ انقضا وجود ندارد. آن مقادیر در اثبات شرکت میکنند اما از سوی مدار مصرف میشوند — هرگز در سیگنالهای عمومی یا روی زنجیره ظاهر نمیشوند. اثباتهای دانشصفر را ببینید برای اینکه چرا این یک تضمین ریاضی است، نه یک خطمشی.
Nullifierها: قرارداد چگونه «یک رای به ازای هر شخص» را اعمال میکند
یک nullifier قطعی است: همان راز + همان event_id همیشه همان nullifier را تولید میکند. اما همچنین یکطرفه است: با داشتن nullifier، هیچکس نمیتواند راز را بازیابی کند یا آن را به هویت کاربر پیوند بزند.
قرارداد بهسادگی هر nullifier را که دیده ثبت میکند. یک اثبات دوم از همان شخص روی همان پیشنهاد همان nullifier را تولید میکند؛ قرارداد آن را رد میکند.
در رویدادهای مختلف، همان شخص nullifierهای متفاوت تولید میکند — طراحانه. این همان چیزی است که سیستم را بین رویدادها ناشناس میکند: هیچکس نمیتواند رای شما به پیشنهاد #۴۲ را به رای شما به پیشنهاد #۴۳ پیوند بزند، با وجود اینکه هر دو معتبرند.
چه چیزی هنوز میتواند روی زنجیره خراب شود
فهرست صادقانه:
| حالت شکست | چه میکنیم دربارهاش |
|---|---|
| بارگذاری کلید راستیآزمایی اشتباه | پیکربندی ثبت مدار بازنگری و پین میشود؛ آزمونها هر VK را پیش از استقرار راستیآزمایی میکنند. |
currentRoot منسوخ (فورک زنجیره، انحراف اسنپشات) | ریشهی ICAO را در StateKeeper خود نگه میداریم؛ M6 ما را تنها ادمین میکند. پشتهی حاکمیتی و M6 را ببینید. |
| حملهی بازپخش | نگاشت nullifier از آن درون یک رویداد جلوگیری میکند. |
| باگ precompile جفتسازی در سطح زنجیره | خطر بهارثرسیده از اتریوم — برای BN254 در تولید رخ نداده. |
| ارتقای قرارداد هوشمند با درب پشتی | با انتقال به مالتیسیگ Gnosis Safe پیش از راهاندازی عمومی کاهش مییابد. |
هیچکدام از اینها شکست رمزنگارانهی خود اثبات نیست. همه خطرات عملیاتی اجرای قرارداد هستند، و با فرایند و حاکمیت قابل رفعاند — که موضوع M6 است.
واژهنامه
| اصطلاح | معنا |
|---|---|
| Groth16 | یک سیستم اثبات zk-SNARK مشخص، ۲۰۱۶. کوچکترین راستیآزما، گستردهپذیرفتهشده. |
| BN254 | منحنی بیضوی که اثباتهای ما روی آن زندگی میکنند. سازگار با جفتسازی، در EVM precompiled. |
| Precompile | یک عمل اتریومی بهصورت کد بومی در یک نشانی رزروشده (0x08 = جفتسازی). ارزان، سریع. |
| کلید راستیآزمایی (VK) | فایل کوچک (~ چند کیلوبایت) که قرارداد برای بررسی اثباتهای یک مدار مشخص بهره میبرد. |
| سیگنالهای عمومی | خروجیهای اعلامشدهی مدار، روی زنجیره مشاهدهشدنی. هرگز شامل دادهی خام سند نیستند. |
| جفتسازی | یک تابع دوخطی e(P, Q) روی نقاط منحنی بیضوی؛ تنها عمل «جادویی» در راستیآزمایی Groth16. |
| Witness | مقادیر میانی سمت تلفن؛ هرگز آپلود نمیشوند. |
| Nullifier | مقدار قطعی ضد-بازپخش هویتپوشاننده، به ازای هر رویداد. |
بعدی
زنجیرهی اعتماد گذرنامه — دادهی موجود در اثبات واقعن از کجا میآید، چرا به آن اعتماد میکنیم، و در برابر چه چیزی نمیتوانیم محافظت کنیم اگر کلید صادرکننده به خطر بیفتد.