خفیہ اسٹیٹ کے لیے زیرو نالج کا استعمال
بلاک چین پر کوئی راز نہیں ہوتے۔ بلاک چین پر جو کچھ بھی پوسٹ کیا جاتا ہے وہ سب کے پڑھنے کے لیے کھلا ہے۔ یہ ضروری ہے، کیونکہ بلاک چین اس پر مبنی ہے کہ کوئی بھی اس کی تصدیق کر سکے۔ تاہم، گیمز اکثر خفیہ اسٹیٹ پر انحصار کرتے ہیں۔ مثال کے طور پر، مائن سویپرopens in a new tab کے گیم کا کوئی مطلب نہیں بنتا اگر آپ صرف ایک بلاک چین ایکسپلورر پر جا کر نقشہ دیکھ سکتے ہیں۔
سب سے آسان حل یہ ہے کہ خفیہ اسٹیٹ کو رکھنے کے لیے ایک سرور کمپونینٹ کا استعمال کیا جائے۔ تاہم، ہم بلاک چین کا استعمال اس لیے کرتے ہیں تاکہ گیم ڈیولپر کی طرف سے دھوکہ دہی کو روکا جا سکے۔ ہمیں سرور کمپونینٹ کی ایمانداری کو یقینی بنانے کی ضرورت ہے۔ سرور اسٹیٹ کا ایک ہیش فراہم کر سکتا ہے، اور زیرو نالج پروفز کا استعمال کر کے یہ ثابت کر سکتا ہے کہ ایک چال کے نتیجے کا حساب لگانے کے لیے استعمال کیا گیا اسٹیٹ صحیح ہے۔
اس مضمون کو پڑھنے کے بعد آپ جان جائیں گے کہ اس قسم کا خفیہ اسٹیٹ رکھنے والا سرور، اسٹیٹ دکھانے کے لیے ایک کلائنٹ، اور دونوں کے درمیان مواصلات کے لیے ایک آن چین کمپونینٹ کیسے بنایا جائے۔ ہم جو اہم ٹولز استعمال کریں گے وہ یہ ہیں:
| ٹول | مقصد | ورژن پر تصدیق شدہ |
|---|---|---|
| Zokratesopens in a new tab | زیرو نالج پروفز اور ان کی تصدیق | 1.1.9 |
| Typescriptopens in a new tab | سرور اور کلائنٹ دونوں کے لیے پروگرامنگ زبان | 5.4.2 |
| Nodeopens in a new tab | سرور چلانا | 20.18.2 |
| Viemopens in a new tab | بلاک چین کے ساتھ مواصلات | 2.9.20 |
| MUDopens in a new tab | آن چین ڈیٹا مینجمنٹ | 2.0.12 |
| Reactopens in a new tab | کلائنٹ یوزر انٹرفیس | 18.2.0 |
| Viteopens in a new tab | کلائنٹ کوڈ کی سرونگ | 4.2.1 |
مائن سویپر کی مثال
مائن سویپرopens in a new tab ایک ایسا گیم ہے جس میں ایک مائن فیلڈ کے ساتھ ایک خفیہ نقشہ شامل ہے۔ کھلاڑی ایک مخصوص مقام پر کھودنے کا انتخاب کرتا ہے۔ اگر اس مقام پر کوئی مائن ہے، تو گیم ختم ہو جاتا ہے۔ ورنہ، کھلاڑی کو اس مقام کے آس پاس کے آٹھ چوکوروں میں مائنز کی تعداد ملتی ہے۔
یہ ایپلیکیشن MUDopens in a new tab کا استعمال کرتے ہوئے لکھی گئی ہے، جو ایک ایسا فریم ورک ہے جو ہمیں کی-ویلیو ڈیٹا بیسopens in a new tab کا استعمال کرتے ہوئے آن چین ڈیٹا اسٹور کرنے اور اس ڈیٹا کو خود بخود آف چین کمپونینٹس کے ساتھ سنکرونائز کرنے کی اجازت دیتا ہے۔ سنکرونائزیشن کے علاوہ، MUD رسائی کنٹرول فراہم کرنا آسان بناتا ہے، اور دوسرے صارفین کے لیے ہماری ایپلیکیشن کو بغیر اجازت کے توسیعopens in a new tab دینا بھی آسان بناتا ہے۔
مائن سویپر کی مثال چلانا
مائن سویپر کی مثال چلانے کے لیے:
-
یقینی بنائیں کہ آپ نے پیشگی شرائط انسٹال کر لی ہیںopens in a new tab: Nodeopens in a new tab, Foundryopens in a new tab,
gitopens in a new tab,pnpmopens in a new tab, اورmprocsopens in a new tab۔ -
ریپوزٹری کو کلون کریں۔
1git clone https://github.com/qbzzt/20240901-secret-state.git -
پیکجز انسٹال کریں۔
1cd 20240901-secret-state/2pnpm install3npm install -g mprocsاگر
pnpm installکے حصے کے طور پر Foundry انسٹال کیا گیا تھا، تو آپ کو کمانڈ لائن شیل کو دوبارہ شروع کرنے کی ضرورت ہے۔ -
کنٹریکٹس کو کمپائل کریں
1cd packages/contracts2forge build3cd ../.. -
پروگرام شروع کریں (بشمول ایک anvilopens in a new tab بلاک چین) اور انتظار کریں۔
1mprocsنوٹ کریں کہ اسٹارٹ اپ میں کافی وقت لگتا ہے۔ پیشرفت دیکھنے کے لیے، پہلے نیچے کے تیر کا استعمال کرتے ہوئے کنٹریکٹس ٹیب پر اسکرول کریں تاکہ MUD کنٹریکٹس کو ڈیپلائے ہوتے دیکھیں۔ جب آپ کو فائل کی تبدیلیوں کا انتظار ہے… کا پیغام ملے، تو کنٹریکٹس ڈیپلائے ہو چکے ہیں اور مزید پیشرفت سرور ٹیب میں ہوگی۔ وہاں، آپ اس وقت تک انتظار کریں جب تک آپ کو ویریفائر ایڈریس: 0x.... کا پیغام نہ مل جائے۔
اگر یہ مرحلہ کامیاب ہو جاتا ہے، تو آپ کو
mprocsاسکرین نظر آئے گی، جس میں بائیں طرف مختلف پروسیسز اور دائیں طرف فی الحال منتخب کردہ پروسیس کے لیے کنسول آؤٹ پٹ ہوگا۔اگر
mprocsکے ساتھ کوئی مسئلہ ہے، تو آپ چاروں پروسیسز کو دستی طور پر چلا سکتے ہیں، ہر ایک کو اپنی کمانڈ لائن ونڈو میں:-
Anvil
1cd packages/contracts2anvil --base-fee 0 --block-time 2 -
کنٹریکٹس
1cd packages/contracts2pnpm mud dev-contracts --rpc http://127.0.0.1:8545 -
سرور
1cd packages/server2pnpm start -
کلائنٹ
1cd packages/client2pnpm run dev
-
-
اب آپ کلائنٹopens in a new tab پر براؤز کر سکتے ہیں، نیا گیم پر کلک کریں، اور کھیلنا شروع کر سکتے ہیں۔
ٹیبلز
ہمیں آن چین کئی ٹیبلزopens in a new tab کی ضرورت ہے۔
-
Configuration: یہ ٹیبل ایک سنگلٹن ہے، اس میں کوئی کلید نہیں ہے اور ایک ہی ریکارڈ ہے۔ اس کا استعمال گیم کی کنفیگریشن کی معلومات کو رکھنے کے لیے کیا جاتا ہے:height: ایک مائن فیلڈ کی اونچائیwidth: ایک مائن فیلڈ کی چوڑائیnumberOfBombs: ہر مائن فیلڈ میں بموں کی تعداد
-
VerifierAddress: یہ ٹیبل بھی ایک سنگلٹن ہے۔ اس کا استعمال کنفیگریشن کے ایک حصے کو رکھنے کے لیے کیا جاتا ہے، یعنی ویریفائر کنٹریکٹ (verifier) کا ایڈریس۔ ہم اس معلومات کوConfigurationٹیبل میں رکھ سکتے تھے، لیکن یہ ایک مختلف کمپونینٹ، یعنی سرور کے ذریعہ سیٹ کیا جاتا ہے، لہذا اسے ایک الگ ٹیبل میں رکھنا آسان ہے۔ -
PlayerGame: کلید کھلاڑی کا ایڈریس ہے۔ ڈیٹا یہ ہے:gameId: 32 بائٹ کی ویلیو جو اس نقشے کا ہیش ہے جس پر کھلاڑی کھیل رہا ہے (گیم شناخت کنندہ)۔win: ایک بولین جو یہ بتاتا ہے کہ آیا کھلاڑی نے گیم جیت لیا ہے۔lose: ایک بولین جو یہ بتاتا ہے کہ آیا کھلاڑی نے گیم ہار دیا ہے۔digNumber: گیم میں کامیاب کھدائیوں کی تعداد۔
-
GamePlayer: یہ ٹیبل الٹی میپنگ رکھتا ہے،gameIdسے کھلاڑی کے ایڈریس تک۔ -
Map: کلید تین ویلیوز کا ایک ٹوپل ہے:gameId: 32 بائٹ کی ویلیو جو اس نقشے کا ہیش ہے جس پر کھلاڑی کھیل رہا ہے (گیم شناخت کنندہ)۔xکوآرڈینیٹyکوآرڈینیٹ
ویلیو ایک واحد نمبر ہے۔ اگر بم کا پتہ چلا تو یہ 255 ہے۔ ورنہ، یہ اس مقام کے ارد گرد بموں کی تعداد جمع ایک ہے۔ ہم صرف بموں کی تعداد کا استعمال نہیں کر سکتے، کیونکہ ڈیفالٹ طور پر EVM میں تمام اسٹوریج اور MUD میں تمام قطار کی ویلیوز صفر ہوتی ہیں۔ ہمیں "کھلاڑی نے ابھی تک یہاں کھدائی نہیں کی ہے" اور "کھلاڑی نے یہاں کھدائی کی، اور پایا کہ ارد گرد صفر بم ہیں" کے درمیان فرق کرنے کی ضرورت ہے۔
اس کے علاوہ، کلائنٹ اور سرور کے درمیان مواصلات آن چین کمپونینٹ کے ذریعے ہوتی ہے۔ یہ بھی ٹیبلز کا استعمال کرتے ہوئے نافذ کیا گیا ہے۔
PendingGame: نیا گیم شروع کرنے کے لیے غیر خدمتی درخواستیں۔PendingDig: ایک مخصوص گیم میں ایک مخصوص جگہ پر کھودنے کے لیے غیر خدمتی درخواستیں۔ یہ ایک آف چین ٹیبلopens in a new tab ہے، جس کا مطلب ہے کہ یہ EVM اسٹوریج میں نہیں لکھا جاتا، یہ صرف ایونٹس کا استعمال کرتے ہوئے آف چین پڑھا جا سکتا ہے۔
ایگزیکیوشن اور ڈیٹا فلو
یہ فلو کلائنٹ، آن چین کمپونینٹ، اور سرور کے درمیان ایگزیکیوشن کو مربوط کرتے ہیں۔
ابتدا
جب آپ mprocs چلاتے ہیں، تو یہ اقدامات ہوتے ہیں:
-
mprocsopens in a new tab چار کمپونینٹس چلاتا ہے:- Anvilopens in a new tab، جو ایک مقامی بلاک چین چلاتا ہے
- کنٹریکٹسopens in a new tab، جو MUD کے لیے کنٹریکٹس کو کمپائل (اگر ضرورت ہو) اور ڈیپلائے کرتا ہے
- کلائنٹopens in a new tab، جو UI اور کلائنٹ کوڈ کو ویب براؤزرز پر سرو کرنے کے لیے Viteopens in a new tab چلاتا ہے۔
- سرورopens in a new tab، جو سرور کے اعمال انجام دیتا ہے
-
contractsپیکج MUD کنٹریکٹس کو ڈیپلائے کرتا ہے اور پھرPostDeploy.s.solاسکرپٹopens in a new tab چلاتا ہے۔ یہ اسکرپٹ کنفیگریشن سیٹ کرتا ہے۔ گٹ ہب سے کوڈ ایک 10x5 مائن فیلڈ کی وضاحت کرتا ہے جس میں آٹھ مائنز ہیںopens in a new tab۔ -
سرورopens in a new tab MUD کو سیٹ اپ کر کےopens in a new tab شروع ہوتا ہے۔ دیگر چیزوں کے علاوہ، یہ ڈیٹا سنکرونائزیشن کو فعال کرتا ہے، تاکہ متعلقہ ٹیبلز کی ایک کاپی سرور کی میموری میں موجود ہو۔
-
سرور ایک فنکشن کو سبسکرائب کرتا ہے تاکہ جب
Configurationٹیبل تبدیل ہوopens in a new tab تو اسے ایگزیکیوٹ کیا جائے۔ یہ فنکشنopens in a new tabPostDeploy.s.solکے ایگزیکیوٹ ہونے اور ٹیبل میں ترمیم کرنے کے بعد کال کیا جاتا ہے۔ -
جب سرور انیشیئلائزیشن فنکشن کے پاس کنفیگریشن ہوتی ہے، تو یہ
zkFunctionsکو کال کرتا ہےopens in a new tab تاکہ سرور کے زیرو نالج حصے کو انیشیئلائز کیا جا سکے۔ یہ اس وقت تک نہیں ہو سکتا جب تک کہ ہمیں کنفیگریشن نہ مل جائے کیونکہ زیرو نالج فنکشنز کو مائن فیلڈ کی چوڑائی اور اونچائی کو مستقل کے طور پر رکھنا ہوتا ہے۔ -
سرور کا زیرو نالج حصہ انیشیئلائز ہونے کے بعد، اگلا قدم زیرو نالج ویریفیکیشن کنٹریکٹ کو بلاک چین پر ڈیپلائے کرناopens in a new tab اور MUD میں ویریفائی ایڈریس سیٹ کرنا ہے۔
-
آخر میں، ہم اپ ڈیٹس کو سبسکرائب کرتے ہیں تاکہ ہم دیکھ سکیں کہ جب کوئی کھلاڑی یا تو نیا گیم شروع کرنےopens in a new tab کی درخواست کرتا ہے یا موجودہ گیم میں کھدائی کرنےopens in a new tab کی درخواست کرتا ہے۔
نیا گیم
جب کھلاڑی نیا گیم کی درخواست کرتا ہے تو یہ ہوتا ہے۔
-
اگر اس کھلاڑی کے لیے کوئی گیم جاری نہیں ہے، یا ایک ہے لیکن اس کا گیم آئی ڈی صفر ہے، تو کلائنٹ ایک نیا گیم بٹنopens in a new tab دکھاتا ہے۔ جب صارف اس بٹن کو دباتا ہے، تو React
newGameفنکشنopens in a new tab چلاتا ہے۔ -
newGameopens in a new tab ایکSystemکال ہے۔ MUD میں تمام کالزWorldکنٹریکٹ کے ذریعے روٹ کی جاتی ہیں، اور زیادہ تر معاملات میں آپ<namespace>__<function name>کو کال کرتے ہیں۔ اس معاملے میں، کالapp__newGameپر ہوتی ہے، جسے MUD پھرGameSystemمیںnewGameپرopens in a new tab روٹ کرتا ہے۔ -
آن چین فنکشن چیک کرتا ہے کہ کھلاڑی کا کوئی گیم جاری نہیں ہے، اور اگر نہیں ہے تو درخواست کو
PendingGameٹیبل میں شامل کر دیتا ہےopens in a new tab۔ -
سرور
PendingGameمیں تبدیلی کا پتہ لگاتا ہے اور سبسکرائب شدہ فنکشنopens in a new tab چلاتا ہے۔ یہ فنکشنnewGameopens in a new tab کو کال کرتا ہے، جو بدلے میںcreateGameopens in a new tab کو کال کرتا ہے۔ -
سب سے پہلے
createGameمناسب تعداد میں مائنز کے ساتھ ایک بے ترتیب نقشہ بناتا ہےopens in a new tab۔ پھر، یہmakeMapBordersopens in a new tab کو خالی بارڈرز کے ساتھ ایک نقشہ بنانے کے لیے کال کرتا ہے، جو Zokrates کے لیے ضروری ہے۔ آخر میں،createGamecalculateMapHashکو کال کرتا ہے، تاکہ نقشے کا ہیش حاصل کیا جا سکے، جسے گیم آئی ڈی کے طور پر استعمال کیا جاتا ہے۔ -
newGameفنکشن نئے گیم کوgamesInProgressمیں شامل کرتا ہے۔ -
سرور جو آخری کام کرتا ہے وہ
app__newGameResponseopens in a new tab کو کال کرنا ہے، جو آن چین ہے۔ یہ فنکشن ایک مختلفSystemمیں ہے،ServerSystemopens in a new tab، تاکہ رسائی کنٹرول کو فعال کیا جا سکے۔ رسائی کنٹرول MUD کنفیگریشن فائلopens in a new tab میں بیان کیا گیا ہے،mud.config.tsopens in a new tab۔رسائی کی فہرست صرف ایک ہی ایڈریس کو
Systemکال کرنے کی اجازت دیتی ہے۔ یہ سرور فنکشنز تک رسائی کو ایک ہی ایڈریس تک محدود کرتا ہے، تاکہ کوئی بھی سرور کی نقالی نہ کر سکے۔ -
آن چین کمپونینٹ متعلقہ ٹیبلز کو اپ ڈیٹ کرتا ہے:
PlayerGameمیں گیم بنائیں۔GamePlayerمیں الٹی میپنگ سیٹ کریں۔PendingGameسے درخواست کو ہٹا دیں۔
-
سرور
PendingGameمیں تبدیلی کی نشاندہی کرتا ہے، لیکن کچھ نہیں کرتا کیونکہwantsGameopens in a new tab غلط ہے۔ -
کلائنٹ پر
gameRecordopens in a new tab کو کھلاڑی کے ایڈریس کے لیےPlayerGameانٹری پر سیٹ کیا جاتا ہے۔ جبPlayerGameتبدیل ہوتا ہے، توgameRecordبھی تبدیل ہوتا ہے۔ -
اگر
gameRecordمیں کوئی ویلیو ہے، اور گیم جیتا یا ہارا نہیں گیا ہے، تو کلائنٹ نقشہ دکھاتا ہےopens in a new tab۔
کھدائی
-
کھلاڑی نقشے کے سیل کے بٹن پر کلک کرتا ہےopens in a new tab، جو
digفنکشنopens in a new tab کو کال کرتا ہے۔ یہ فنکشنdigکو آن چینopens in a new tab کال کرتا ہے۔ -
آن چین کمپونینٹ کئی سینیٹی چیکس انجام دیتا ہےopens in a new tab، اور اگر کامیاب ہو جاتا ہے تو کھدائی کی درخواست کو
PendingDigopens in a new tab میں شامل کر دیتا ہے۔ -
سرور
PendingDigمیں تبدیلی کا پتہ لگاتا ہےopens in a new tab۔ اگر یہ درست ہےopens in a new tab، تو یہ زیرو نالج کوڈ کو کال کرتا ہےopens in a new tab (نیچے بیان کیا گیا ہے) تاکہ نتیجہ اور اس کے درست ہونے کا ثبوت دونوں پیدا کیا جا سکے۔ -
سرورopens in a new tab آن چین
digResponseopens in a new tab کو کال کرتا ہے۔ -
digResponseدو کام کرتا ہے۔ سب سے پہلے، یہ زیرو نالج پروفopens in a new tab کو چیک کرتا ہے۔ پھر، اگر پروف چیک ہو جاتا ہے، تو یہprocessDigResultopens in a new tab کو کال کرتا ہے تاکہ نتیجے کو دراصل پروسیس کیا جا سکے۔ -
processDigResultچیک کرتا ہے کہ آیا گیم ہارopens in a new tab گیا ہے یا جیتopens in a new tab لیا گیا ہے، اورMap، یعنی آن چین نقشے کو اپ ڈیٹ کرتا ہےopens in a new tab۔ -
کلائنٹ خود بخود اپ ڈیٹس اٹھاتا ہے اور کھلاڑی کو دکھائے گئے نقشے کو اپ ڈیٹ کرتا ہےopens in a new tab، اور اگر قابل اطلاق ہو تو کھلاڑی کو بتاتا ہے کہ یہ جیت ہے یا ہار۔
Zokrates کا استعمال
اوپر بیان کیے گئے فلو میں ہم نے زیرو نالج حصوں کو نظر انداز کر دیا، انہیں ایک بلیک باکس کے طور پر سمجھا۔ اب آئیے اسے کھول کر دیکھتے ہیں کہ وہ کوڈ کیسے لکھا گیا ہے۔
نقشے کی ہیشنگ
ہم یہ جاوا اسکرپٹ کوڈopens in a new tab Poseidonopens in a new tab کو نافذ کرنے کے لیے استعمال کر سکتے ہیں، جو ہمارا استعمال کردہ Zokrates ہیش فنکشن ہے۔ تاہم، جبکہ یہ تیز ہوگا، یہ صرف Zokrates ہیش فنکشن کا استعمال کرنے سے زیادہ پیچیدہ بھی ہوگا۔ یہ ایک ٹیوٹوریل ہے، اور اس لیے کوڈ کو سادگی کے لیے بہتر بنایا گیا ہے، نہ کہ کارکردگی کے لیے۔ لہذا، ہمیں دو مختلف Zokrates پروگراموں کی ضرورت ہے، ایک صرف ایک نقشے (hash) کے ہیش کا حساب لگانے کے لیے اور دوسرا نقشے (dig) پر کسی مقام پر کھدائی کے نتیجے کا زیرو نالج پروف بنانے کے لیے۔
ہیش فنکشن
یہ وہ فنکشن ہے جو ایک نقشے کے ہیش کا حساب لگاتا ہے۔ ہم اس کوڈ کا لائن بہ لائن جائزہ لیں گے۔
1import "hashes/poseidon/poseidon.zok" as poseidon;2import "utils/pack/bool/pack128.zok" as pack128;یہ دو لائنیں Zokrates اسٹینڈرڈ لائبریریopens in a new tab سے دو فنکشن درآمد کرتی ہیں۔ پہلا فنکشنopens in a new tab ایک Poseidon ہیشopens in a new tab ہے۔ یہ field عناصرopens in a new tab کی ایک صف لیتا ہے اور ایک field لوٹاتا ہے۔
Zokrates میں فیلڈ عنصر عام طور پر 256 بٹس سے کم لمبا ہوتا ہے، لیکن زیادہ نہیں۔ کوڈ کو آسان بنانے کے لیے، ہم نقشے کو 512 بٹس تک محدود کرتے ہیں، اور چار فیلڈز کی ایک صف کو ہیش کرتے ہیں، اور ہر فیلڈ میں ہم صرف 128 بٹس استعمال کرتے ہیں۔ pack128 فنکشنopens in a new tab اس مقصد کے لیے 128 بٹس کی ایک صف کو field میں تبدیل کرتا ہے۔
1 def hashMap(bool[${width+2}][${height+2}] map) -> field {یہ لائن ایک فنکشن کی تعریف شروع کرتی ہے۔ hashMap کو map نامی ایک ہی پیرامیٹر ملتا ہے، جو ایک دو جہتی bool(ean) صف ہے۔ نقشے کا سائز width+2 ضرب height+2 ہے ان وجوہات کی بنا پر جو نیچے بیان کی گئی ہیں۔
ہم ${width+2} اور ${height+2} استعمال کر سکتے ہیں کیونکہ Zokrates پروگرام اس ایپلیکیشن میں ٹیمپلیٹ اسٹرنگزopens in a new tab کے طور پر محفوظ ہیں۔ ${ اور } کے درمیان کوڈ کا جاوا اسکرپٹ کے ذریعے جائزہ لیا جاتا ہے، اور اس طرح پروگرام کو مختلف نقشے کے سائز کے لیے استعمال کیا جا سکتا ہے۔ نقشہ پیرامیٹر میں اس کے چاروں طرف ایک مقام چوڑا بارڈر ہے جس میں کوئی بم نہیں ہے، یہی وجہ ہے کہ ہمیں چوڑائی اور اونچائی میں دو کا اضافہ کرنے کی ضرورت ہے۔
واپسی کی قیمت ایک field ہے جس میں ہیش ہوتا ہے۔
1 bool[512] mut map1d = [false; 512];نقشہ دو جہتی ہے۔ تاہم، pack128 فنکشن دو جہتی صفوں کے ساتھ کام نہیں کرتا ہے۔ لہذا ہم پہلے نقشے کو 512 بائٹ کی صف میں ہموار کرتے ہیں، map1d کا استعمال کرتے ہوئے۔ ڈیفالٹ کے طور پر Zokrates متغیرات مستقل ہوتے ہیں، لیکن ہمیں اس صف کو ایک لوپ میں اقدار تفویض کرنے کی ضرورت ہے، لہذا ہم اسے mutopens in a new tab کے طور پر بیان کرتے ہیں۔
ہمیں صف کو شروع کرنے کی ضرورت ہے کیونکہ Zokrates میں undefined نہیں ہے۔ تاثر [false; 512] کا مطلب ہے 512 false اقدار کی ایک صفopens in a new tab۔
1 u32 mut counter = 0;ہمیں ان بٹس کے درمیان فرق کرنے کے لیے ایک کاؤنٹر کی بھی ضرورت ہے جو ہم نے map1d میں پہلے ہی بھر دیے ہیں اور جو نہیں بھرے۔
1 for u32 x in 0..${width+2} {یہ ہے کہ آپ Zokrates میں for لوپopens in a new tab کا اعلان کیسے کرتے ہیں۔ ایک Zokrates for لوپ کی مقررہ حدود ہونی چاہئیں، کیونکہ جبکہ یہ ایک لوپ کی طرح لگتا ہے، کمپائلر دراصل اسے "کھول" دیتا ہے۔ تاثر ${width+2} ایک کمپائل ٹائم مستقل ہے کیونکہ width ٹائپ اسکرپٹ کوڈ کے ذریعے کمپائلر کو کال کرنے سے پہلے سیٹ کیا جاتا ہے۔
1 for u32 y in 0..${height+2} {2 map1d[counter] = map[x][y];3 counter = counter+1;4 }5 }نقشے میں ہر مقام کے لیے، اس قدر کو map1d صف میں ڈالیں اور کاؤنٹر میں اضافہ کریں۔
1 field[4] hashMe = [2 pack128(map1d[0..128]),3 pack128(map1d[128..256]),4 pack128(map1d[256..384]),5 pack128(map1d[384..512])6 ];pack128 map1d سے چار field اقدار کی ایک صف بنانے کے لیے۔ Zokrates میں array[a..b] کا مطلب ہے صف کا وہ ٹکڑا جو a سے شروع ہوتا ہے اور b-1 پر ختم ہوتا ہے۔
1 return poseidon(hashMe);2}اس صف کو ہیش میں تبدیل کرنے کے لیے poseidon کا استعمال کریں۔
ہیش پروگرام
سرور کو گیم شناخت کنندہ بنانے کے لیے براہ راست hashMap کو کال کرنے کی ضرورت ہے۔ تاہم، Zokrates صرف main فنکشن کو شروع کرنے کے لیے کال کر سکتا ہے، لہذا ہم ایک main کے ساتھ ایک پروگرام بناتے ہیں جو ہیش فنکشن کو کال کرتا ہے۔
1${hashFragment}23def main(bool[${width+2}][${height+2}] map) -> field {4 return hashMap(map);5}کھدائی پروگرام
یہ ایپلیکیشن کا زیرو نالج حصہ کا دل ہے، جہاں ہم وہ ثبوت تیار کرتے ہیں جو کھدائی کے نتائج کی تصدیق کے لیے استعمال ہوتے ہیں۔
1${hashFragment}23// The number of mines in location (x,y)4def map2mineCount(bool[${width+2}][${height+2}] map, u32 x, u32 y) -> u8 {5 return if map[x+1][y+1] { 1 } else { 0 };6}نقشے کا بارڈر کیوں
زیرو نالج پروف حسابی سرکٹسopens in a new tab کا استعمال کرتے ہیں، جن میں if اسٹیٹمنٹ کا کوئی آسان مساوی نہیں ہوتا ہے۔ اس کے بجائے، وہ مشروط آپریٹرopens in a new tab کے مساوی کا استعمال کرتے ہیں۔ اگر a صفر یا ایک ہو سکتا ہے، تو آپ if a { b } else { c } کا حساب ab+(1-a)c کے طور پر کر سکتے ہیں۔
اس کی وجہ سے، ایک Zokrates if اسٹیٹمنٹ ہمیشہ دونوں شاخوں کا جائزہ لیتا ہے۔ مثال کے طور پر، اگر آپ کے پاس یہ کوڈ ہے:
1bool[5] arr = [false; 5];2u32 index=10;3return if index>4 { 0 } else { arr[index] }اس میں خرابی ہوگی، کیونکہ اسے arr[10] کا حساب لگانے کی ضرورت ہے، چاہے وہ قدر بعد میں صفر سے ضرب دی جائے۔
یہی وجہ ہے کہ ہمیں نقشے کے چاروں طرف ایک مقام چوڑا بارڈر کی ضرورت ہے۔ ہمیں کسی مقام کے ارد گرد مائنز کی کل تعداد کا حساب لگانے کی ضرورت ہے، اور اس کا مطلب ہے کہ ہمیں اس مقام سے ایک قطار اوپر اور نیچے، بائیں اور دائیں کو دیکھنے کی ضرورت ہے، جہاں ہم کھدائی کر رہے ہیں۔ جس کا مطلب ہے کہ وہ مقام Zokrates کو فراہم کردہ نقشے کی صف میں موجود ہونا چاہیے۔
1def main(private bool[${width+2}][${height+2}] map, u32 x, u32 y) -> (field, u8) {ڈیفالٹ کے طور پر Zokrates ثبوتوں میں ان کے ان پٹ شامل ہوتے ہیں۔ یہ جاننا کوئی فائدہ مند نہیں ہے کہ کسی جگہ کے ارد گرد پانچ مائنز ہیں جب تک کہ آپ کو حقیقت میں یہ نہ معلوم ہو کہ وہ کون سی جگہ ہے (اور آپ اسے صرف اپنی درخواست سے نہیں ملا سکتے، کیونکہ تب پروور مختلف اقدار کا استعمال کر سکتا ہے اور آپ کو اس کے بارے میں نہیں بتا سکتا)۔ تاہم، ہمیں نقشے کو خفیہ رکھنے کی ضرورت ہے، جبکہ اسے Zokrates کو فراہم کرتے ہوئے۔ حل یہ ہے کہ ایک private پیرامیٹر کا استعمال کیا جائے، ایک ایسا جو ثبوت سے ظاہر نہیں ہوتا ہے۔
اس سے غلط استعمال کا ایک اور راستہ کھلتا ہے۔ پروور صحیح کوآرڈینیٹس کا استعمال کر سکتا ہے، لیکن مقام کے ارد گرد کسی بھی تعداد میں مائنز کے ساتھ ایک نقشہ بنا سکتا ہے، اور ممکنہ طور پر خود مقام پر بھی۔ اس غلط استعمال کو روکنے کے لیے، ہم زیرو نالج پروف کو نقشے کا ہیش شامل کرتے ہیں، جو گیم شناخت کنندہ ہے۔
1 return (hashMap(map),یہاں واپسی کی قیمت ایک ٹوپل ہے جس میں نقشہ ہیش صف اور کھدائی کا نتیجہ شامل ہے۔
1 if map2mineCount(map, x, y) > 0 { 0xFF } else {اگر خود مقام پر کوئی بم ہو تو ہم 255 کو ایک خاص قدر کے طور پر استعمال کرتے ہیں۔
1 map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) +2 map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) +3 map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1)4 }5 );6}اگر کھلاڑی نے کسی مائن کو نہیں مارا ہے، تو مقام کے ارد گرد کے علاقے کے لیے مائن کاؤنٹ شامل کریں اور اسے واپس کریں۔
TypeScript سے Zokrates کا استعمال
Zokrates کا ایک کمانڈ لائن انٹرفیس ہے، لیکن اس پروگرام میں ہم اسے TypeScript کوڈopens in a new tab میں استعمال کرتے ہیں۔
Zokrates تعریفوں پر مشتمل لائبریری کو zero-knowledge.tsopens in a new tab کہا جاتا ہے۔
1import { initialize as zokratesInitialize } from "zokrates-js"Zokrates جاوا اسکرپٹ بائنڈنگزopens in a new tab کو درآمد کریں۔ ہمیں صرف initializeopens in a new tab فنکشن کی ضرورت ہے کیونکہ یہ ایک وعدہ لوٹاتا ہے جو تمام Zokrates تعریفوں کو حل کرتا ہے۔
1export const zkFunctions = async (width: number, height: number) : Promise<any> => {Zokrates کی طرح، ہم بھی صرف ایک فنکشن برآمد کرتے ہیں، جو غیر ہم آہنگopens in a new tab بھی ہے۔ جب یہ بالآخر واپس آتا ہے، تو یہ کئی فنکشن فراہم کرتا ہے جیسا کہ ہم نیچے دیکھیں گے۔
1const zokrates = await zokratesInitialize()Zokrates کو شروع کریں، لائبریری سے ہمیں ہر چیز حاصل کریں۔
1const hashFragment = `2 import "utils/pack/bool/pack128.zok" as pack128;3 import "hashes/poseidon/poseidon.zok" as poseidon;4 .5 .6 .7 }8 `910const hashProgram = `11 ${hashFragment}12 .13 .14 .15 `1617const digProgram = `18 ${hashFragment}19 .20 .21 .22 `سب دکھائیںاگلا ہمارے پاس ہیش فنکشن اور دو Zokrates پروگرام ہیں جو ہم نے اوپر دیکھے۔
1const digCompiled = zokrates.compile(digProgram)2const hashCompiled = zokrates.compile(hashProgram)یہاں ہم ان پروگراموں کو کمپائل کرتے ہیں۔
1// Create the keys for zero knowledge verification.2// On a production system you'd want to use a setup ceremony.3// (https://zokrates.github.io/toolbox/trusted_setup.html#initializing-a-phase-2-ceremony).4const keySetupResults = zokrates.setup(digCompiled.program, "")5const verifierKey = keySetupResults.vk6const proverKey = keySetupResults.pkایک پروڈکشن سسٹم پر ہم ایک زیادہ پیچیدہ سیٹ اپ تقریبopens in a new tab کا استعمال کر سکتے ہیں، لیکن یہ ایک مظاہرے کے لیے کافی ہے۔ یہ کوئی مسئلہ نہیں ہے کہ صارفین پروور کی جان سکتے ہیں - وہ پھر بھی اسے چیزوں کو ثابت کرنے کے لیے استعمال نہیں کر سکتے جب تک کہ وہ سچ نہ ہوں۔ کیونکہ ہم اینٹروپی کی وضاحت کرتے ہیں (دوسرا پیرامیٹر، "")، نتائج ہمیشہ ایک جیسے ہی ہوں گے۔
نوٹ: Zokrates پروگراموں کی تالیف اور کلید کی تخلیق سست عمل ہیں۔ انہیں ہر بار دہرانے کی ضرورت نہیں ہے، صرف اس وقت جب نقشے کا سائز تبدیل ہوتا ہے۔ ایک پروڈکشن سسٹم پر آپ انہیں ایک بار کریں گے، اور پھر آؤٹ پٹ کو اسٹور کریں گے۔ میں یہاں صرف سادگی کی خاطر ایسا نہیں کر رہا ہوں۔
calculateMapHash
1const calculateMapHash = function (hashMe: boolean[][]): string {2 return (3 "0x" +4 BigInt(zokrates.computeWitness(hashCompiled, [hashMe]).output.slice(1, -1))5 .toString(16)6 .padStart(64, "0")7 )8}computeWitnessopens in a new tab فنکشن دراصل Zokrates پروگرام چلاتا ہے۔ یہ دو فیلڈز کے ساتھ ایک ڈھانچہ لوٹاتا ہے: output، جو ایک JSON سٹرنگ کے طور پر پروگرام کا آؤٹ پٹ ہے، اور witness، جو نتیجے کا زیرو نالج پروف بنانے کے لیے درکار معلومات ہے۔ یہاں ہمیں صرف آؤٹ پٹ کی ضرورت ہے۔
آؤٹ پٹ "31337" کی شکل میں ایک سٹرنگ ہے، جو کوٹیشن مارکس میں بند ایک اعشاریہ نمبر ہے۔ لیکن viem کے لیے ہمیں جو آؤٹ پٹ چاہیے وہ 0x60A7 کی شکل میں ایک ہیکساڈیسیمل نمبر ہے۔ لہذا ہم کوٹیشن مارکس کو ہٹانے کے لیے .slice(1,-1) کا استعمال کرتے ہیں اور پھر باقی سٹرنگ کو، جو ایک اعشاریہ نمبر ہے، ایک BigIntopens in a new tab میں تبدیل کرنے کے لیے BigInt کا استعمال کرتے ہیں۔ .toString(16) اس BigInt کو ایک ہیکساڈیسیمل سٹرنگ میں تبدیل کرتا ہے، اور "0x"+ ہیکساڈیسیمل نمبروں کے لیے مارکر شامل کرتا ہے۔
1// Dig and return a zero knowledge proof of the result2// (server-side code)زیرو نالج پروف میں عوامی ان پٹس (x اور y) اور نتائج (نقشے کا ہیش اور بموں کی تعداد) شامل ہیں۔
1 const zkDig = function(map: boolean[][], x: number, y: number) : any {2 if (x<0 || x>=width || y<0 || y>=height)3 throw new Error("Trying to dig outside the map")یہ چیک کرنا کہ آیا کوئی انڈیکس Zokrates میں حد سے باہر ہے، ایک مسئلہ ہے، لہذا ہم اسے یہاں کرتے ہیں۔
1const runResults = zokrates.computeWitness(digCompiled, [map, `${x}`, `${y}`])کھدائی پروگرام پر عمل کریں۔
1 const proof = zokrates.generateProof(2 digCompiled.program,3 runResults.witness,4 proverKey)56 return proof7 }generateProofopens in a new tab کا استعمال کریں اور ثبوت واپس کریں۔
1const solidityVerifier = `2 // Map size: ${width} x ${height}3 \n${zokrates.exportSolidityVerifier(verifierKey)}4 `ایک Solidity ویریفائر، ایک سمارٹ کنٹریکٹ جسے ہم بلاک چین پر تعینات کر سکتے ہیں اور digCompiled.program کے ذریعے تیار کردہ ثبوتوں کی تصدیق کے لیے استعمال کر سکتے ہیں۔
1 return {2 zkDig,3 calculateMapHash,4 solidityVerifier,5 }6}آخر میں، ہر وہ چیز واپس کریں جس کی دوسرے کوڈ کو ضرورت ہو سکتی ہے۔
سیکیورٹی ٹیسٹ
سیکیورٹی ٹیسٹ اہم ہیں کیونکہ ایک فنکشنلٹی بگ بالآخر خود کو ظاہر کر دے گا۔ لیکن اگر ایپلیکیشن غیر محفوظ ہے، تو یہ ممکنہ طور پر ایک طویل عرصے تک چھپی رہے گی اس سے پہلے کہ یہ کسی کے دھوکہ دہی اور دوسروں سے تعلق رکھنے والے وسائل سے بچ نکلنے سے ظاہر ہو۔
اجازتیں
اس گیم میں ایک مراعات یافتہ ادارہ ہے، سرور۔ یہ واحد صارف ہے جسے ServerSystemopens in a new tab میں فنکشنز کو کال کرنے کی اجازت ہے۔ ہم castopens in a new tab کا استعمال کر سکتے ہیں تاکہ یہ تصدیق کی جا سکے کہ اجازت یافتہ فنکشنز کی کالز صرف سرور اکاؤنٹ کے طور پر ہی کی جا سکتی ہیں۔
سرور کی نجی کلید setupNetwork.ts میں ہےopens in a new tab۔
-
anvil(بلاک چین) چلانے والے کمپیوٹر پر، یہ ماحولیاتی متغیرات سیٹ کریں۔1WORLD_ADDRESS=0x8d8b6b8414e1e3dcfd4168561b9be6bd3bf6ec4b2UNAUTHORIZED_KEY=0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a3AUTHORIZED_KEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d -
castکا استعمال کریں تاکہ تصدیق کنندہ کا پتہ ایک غیر مجاز پتے کے طور پر سیٹ کرنے کی کوشش کی جا سکے۔1cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $UNAUTHORIZED_KEYنہ صرف
castایک ناکامی کی اطلاع دیتا ہے، بلکہ آپ براؤزر پر گیم میں MUD Dev Tools کھول سکتے ہیں، ٹیبلز پر کلک کر سکتے ہیں، اور app__VerifierAddress کو منتخب کر سکتے ہیں۔ دیکھیں کہ پتہ صفر نہیں ہے۔ -
ویریفائر ایڈریس کو سرور کے ایڈریس کے طور پر سیٹ کریں۔
1cast send $WORLD_ADDRESS 'app__setVerifier(address)' `cast address-zero` --private-key $AUTHORIZED_KEYapp__VerifiedAddress میں پتہ اب صفر ہونا چاہیے۔
ایک ہی System میں تمام MUD فنکشنز ایک ہی ایکسیس کنٹرول سے گزرتے ہیں، لہذا میں اس ٹیسٹ کو کافی سمجھتا ہوں۔ اگر آپ نہیں کرتے ہیں، تو آپ ServerSystemopens in a new tab میں دیگر فنکشنز کو چیک کر سکتے ہیں۔
زیرو نالج کے غلط استعمال
Zokrates کی تصدیق کے لیے ریاضی اس ٹیوٹوریل (اور میری صلاحیتوں) کے دائرہ سے باہر ہے۔ تاہم، ہم زیرو نالج کوڈ پر مختلف چیک چلا سکتے ہیں تاکہ یہ تصدیق کی جا سکے کہ اگر اسے صحیح طریقے سے نہیں کیا گیا تو یہ ناکام ہو جاتا ہے۔ ان تمام ٹیسٹوں کے لیے ہمیں zero-knowledge.tsopens in a new tab کو تبدیل کرنے اور پوری ایپلیکیشن کو دوبارہ شروع کرنے کی ضرورت ہوگی۔ سرور پروسیس کو دوبارہ شروع کرنا کافی نہیں ہے، کیونکہ یہ ایپلیکیشن کو ایک ناممکن حالت میں ڈال دیتا ہے (کھلاڑی کا ایک گیم جاری ہے، لیکن گیم اب سرور کے لیے دستیاب نہیں ہے)۔
غلط جواب
سب سے آسان امکان زیرو نالج پروف میں غلط جواب فراہم کرنا ہے۔ ایسا کرنے کے لیے، ہم zkDig کے اندر جاتے ہیں اور لائن 91 میں ترمیم کرتے ہیںopens in a new tab:
1proof.inputs[3] = "0x" + "1".padStart(64, "0")اس کا مطلب ہے کہ ہم ہمیشہ دعویٰ کریں گے کہ ایک بم ہے، چاہے صحیح جواب کچھ بھی ہو۔ اس ورژن کے ساتھ کھیلنے کی کوشش کریں، اور آپ pnpm dev اسکرین کے سرور ٹیب میں یہ خرابی دیکھیں گے:
1 cause: {2 code: 3,3 message: 'execution reverted: revert: Zero knowledge verification fail',4 data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000500000000000000000000000000000000000000000000000205a65726f206b6e6f776c6564676520766572696669636174696f66e206661696c'7 },تو اس قسم کی دھوکہ دہی ناکام ہو جاتی ہے۔
غلط ثبوت
کیا ہوتا ہے اگر ہم صحیح معلومات فراہم کریں، لیکن ثبوت کا ڈیٹا غلط ہو؟ اب، لائن 91 کو اس سے بدل دیں:
1proof.proof = {2 a: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],3 b: [4 ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],5 ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],6 ],7 c: ["0x" + "1".padStart(64, "0"), "0x" + "2".padStart(64, "0")],8}یہ اب بھی ناکام رہتا ہے، لیکن اب یہ بغیر کسی وجہ کے ناکام ہوجاتا ہے کیونکہ یہ ویریفائر کال کے دوران ہوتا ہے۔
ایک صارف زیرو ٹرسٹ کوڈ کی تصدیق کیسے کر سکتا ہے؟
اسمارٹ معاہدوں کی تصدیق کرنا نسبتاً آسان ہے۔ عام طور پر، ڈیولپر سورس کوڈ کو ایک بلاک ایکسپلورر پر شائع کرتا ہے، اور بلاک ایکسپلورر اس بات کی تصدیق کرتا ہے کہ سورس کوڈ معاہدے کی تعیناتی کے لین دین میں کوڈ کو کمپائل کرتا ہے۔ MUD Systems کے معاملے میں یہ تھوڑا زیادہ پیچیدہopens in a new tab ہے، لیکن زیادہ نہیں۔
یہ زیرو نالج کے ساتھ زیادہ مشکل ہے۔ ویریفائر میں کچھ مستقل شامل ہوتے ہیں اور ان پر کچھ حسابات چلاتے ہیں۔ یہ آپ کو نہیں بتاتا کہ کیا ثابت کیا جا رہا ہے۔
1 function verifyingKey() pure internal returns (VerifyingKey memory vk) {2 vk.alpha = Pairing.G1Point(uint256(0x0f43f4fe7b5c2326fed4ac6ed2f4003ab9ab4ea6f667c2bdd77afb068617ee16), uint256(0x25a77832283f9726935219b5f4678842cda465631e72dbb24708a97ba5d0ce6f));3 vk.beta = Pairing.G2Point([uint256(0x2cebd0fbd21aca01910581537b21ae4fed46bc0e524c055059aa164ba0a6b62b), uint256(0x18fd4a7bc386cf03a95af7163d5359165acc4e7961cb46519e6d9ee4a1e2b7e9)], [uint256(0x11449dee0199ef6d8eebfe43b548e875c69e7ce37705ee9a00c81fe52f11a009), uint256(0x066d0c83b32800d3f335bb9e8ed5e2924cf00e77e6ec28178592eac9898e1a00)]);حل، کم از کم جب تک بلاک ایکسپلوررز اپنے صارف انٹرفیس میں Zokrates کی تصدیق شامل نہیں کر لیتے، یہ ہے کہ ایپلیکیشن ڈیولپرز Zokrates پروگراموں کو دستیاب کرائیں، اور کم از کم کچھ صارفین انہیں مناسب تصدیقی کلید کے ساتھ خود کمپائل کریں۔
ایسا کرنے کے لیے:
-
ایک فائل بنائیں،
dig.zok، Zokrates پروگرام کے ساتھ۔ نیچے دیا گیا کوڈ یہ فرض کرتا ہے کہ آپ نے اصل نقشے کا سائز، 10x5، رکھا ہے۔1 import "utils/pack/bool/pack128.zok" as pack128;2 import "hashes/poseidon/poseidon.zok" as poseidon;34 def hashMap(bool[12][7] map) -> field {5 bool[512] mut map1d = [false; 512];6 u32 mut counter = 0;78 for u32 x in 0..12 {9 for u32 y in 0..7 {10 map1d[counter] = map[x][y];11 counter = counter+1;12 }13 }1415 field[4] hashMe = [16 pack128(map1d[0..128]),17 pack128(map1d[128..256]),18 pack128(map1d[256..384]),19 pack128(map1d[384..512])20 ];2122 return poseidon(hashMe);23 }242526 // The number of mines in location (x,y)27 def map2mineCount(bool[12][7] map, u32 x, u32 y) -> u8 {28 return if map[x+1][y+1] { 1 } else { 0 };29 }3031 def main(private bool[12][7] map, u32 x, u32 y) -> (field, u8) {32 return (hashMap(map) ,33 if map2mineCount(map, x, y) > 0 { 0xFF } else {34 map2mineCount(map, x-1, y-1) + map2mineCount(map, x, y-1) + map2mineCount(map, x+1, y-1) +35 map2mineCount(map, x-1, y) + map2mineCount(map, x+1, y) +36 map2mineCount(map, x-1, y+1) + map2mineCount(map, x, y+1) + map2mineCount(map, x+1, y+1)37 }38 );39 }سب دکھائیں -
Zokrates کوڈ کو کمپائل کریں اور تصدیقی کلید بنائیں۔ تصدیقی کلید اسی اینٹروپی کے ساتھ بنانی ہوگی جو اصل سرور میں استعمال کی گئی تھی، اس معاملے میں ایک خالی سٹرنگopens in a new tab۔
1zokrates compile --input dig.zok2zokrates setup -e "" -
اپنا Solidity ویریفائر خود بنائیں، اور تصدیق کریں کہ یہ بلاک چین پر موجود ویریفائر سے فنکشنل طور پر یکساں ہے (سرور ایک تبصرہ شامل کرتا ہے، لیکن یہ اہم نہیں ہے)۔
1zokrates export-verifier2diff verifier.sol ~/20240901-secret-state/packages/contracts/src/verifier.sol
ڈیزائن کے فیصلے
کسی بھی کافی پیچیدہ ایپلیکیشن میں مسابقتی ڈیزائن کے اہداف ہوتے ہیں جن کے لیے سمجھوتہ کی ضرورت ہوتی ہے۔ آئیے کچھ سمجھوتوں کو دیکھتے ہیں اور یہ کہ موجودہ حل دوسرے اختیارات سے کیوں بہتر ہے۔
زیرو نالج کیوں
مائن سویپر کے لیے آپ کو حقیقت میں زیرو نالج کی ضرورت نہیں ہے۔ سرور ہمیشہ نقشہ رکھ سکتا ہے، اور پھر گیم ختم ہونے پر اس سب کو ظاہر کر سکتا ہے۔ پھر، گیم کے اختتام پر، سمارٹ کنٹریکٹ نقشے کے ہیش کا حساب لگا سکتا ہے، تصدیق کر سکتا ہے کہ یہ میل کھاتا ہے، اور اگر ایسا نہیں ہوتا ہے تو سرور کو سزا دے سکتا ہے یا گیم کو مکمل طور پر نظر انداز کر سکتا ہے۔
میں نے یہ آسان حل استعمال نہیں کیا کیونکہ یہ صرف اچھی طرح سے متعین اختتامی حالت والے مختصر گیمز کے لیے کام کرتا ہے۔ جب ایک گیم ممکنہ طور پر لامحدود ہو (جیسے کہ خود مختار دنیاؤںopens in a new tab کے معاملے میں)، آپ کو ایک ایسے حل کی ضرورت ہے جو حالت کو ظاہر کیے بغیر ثابت کرے۔
ایک ٹیوٹوریل کے طور پر اس مضمون کو ایک مختصر گیم کی ضرورت تھی جو سمجھنے میں آسان ہو، لیکن یہ تکنیک طویل گیمز کے لیے سب سے زیادہ مفید ہے۔
Zokrates کیوں؟
Zokratesopens in a new tab واحد زیرو نالج لائبریری دستیاب نہیں ہے، لیکن یہ ایک عام، امپیریٹوopens in a new tab پروگرامنگ زبان کی طرح ہے اور بولین متغیرات کو سپورٹ کرتی ہے۔
آپ کی ایپلیکیشن کے لیے، مختلف ضروریات کے ساتھ، آپ Circumopens in a new tab یا Cairoopens in a new tab کا استعمال کرنا پسند کر سکتے ہیں۔
Zokrates کو کب کمپائل کریں
اس پروگرام میں ہم Zokrates پروگراموں کو ہر بار سرور شروع ہونے پرopens in a new tab کمپائل کرتے ہیں۔ یہ واضح طور پر وسائل کا ضیاع ہے، لیکن یہ ایک ٹیوٹوریل ہے، جو سادگی کے لیے بہتر بنایا گیا ہے۔
اگر میں پروڈکشن لیول کی ایپلیکیشن لکھ رہا ہوتا، تو میں چیک کرتا کہ آیا میرے پاس اس مائن فیلڈ سائز پر کمپائل شدہ Zokrates پروگراموں کے ساتھ ایک فائل ہے، اور اگر ایسا ہے تو اسے استعمال کرتا۔ یہی بات آن چین پر ویریفائر کنٹریکٹ کی تعیناتی پر بھی لاگو ہوتی ہے۔
ویریفائر اور پروور کیز بنانا
کلید کی تخلیقopens in a new tab ایک اور خالص حساب ہے جسے ایک دیے گئے مائن فیلڈ سائز کے لیے ایک سے زیادہ بار کرنے کی ضرورت نہیں ہے۔ ایک بار پھر، یہ صرف سادگی کی خاطر ایک بار کیا جاتا ہے۔
مزید برآں، ہم ایک سیٹ اپ تقریبopens in a new tab کا استعمال کر سکتے ہیں۔ ایک سیٹ اپ تقریب کا فائدہ یہ ہے کہ آپ کو زیرو نالج پروف پر دھوکہ دینے کے لیے یا تو اینٹروپی یا ہر شریک سے کچھ درمیانی نتیجہ کی ضرورت ہوتی ہے۔ اگر کم از کم ایک تقریب کا شریک ایماندار ہے اور اس معلومات کو حذف کر دیتا ہے، تو زیرو نالج پروف کچھ حملوں سے محفوظ ہیں۔ تاہم، یہ تصدیق کرنے کا کوئی میکانزم نہیں ہے کہ معلومات کو ہر جگہ سے حذف کر دیا گیا ہے۔ اگر زیرو نالج پروف انتہائی اہم ہیں، تو آپ سیٹ اپ تقریب میں حصہ لینا چاہتے ہیں۔
یہاں ہم پرپیچوئل پاورز آف ٹاؤopens in a new tab پر انحصار کرتے ہیں، جس میں درجنوں شرکاء تھے۔ یہ شاید کافی محفوظ ہے، اور بہت آسان ہے۔ ہم کلید کی تخلیق کے دوران اینٹروپی بھی شامل نہیں کرتے ہیں، جس سے صارفین کے لیے زیرو نالج کنفیگریشن کی تصدیق کرنا آسان ہو جاتا ہے۔
کہاں تصدیق کریں
ہم زیرو نالج پروف کو یا تو آن چین (جس پر گیس خرچ ہوتی ہے) یا کلائنٹ میں ( verifyopens in a new tab کا استعمال کرتے ہوئے) تصدیق کر سکتے ہیں۔ میں نے پہلا انتخاب کیا، کیونکہ یہ آپ کو ویریفائر کی تصدیق کرنے کی اجازت دیتا ہے اور پھر اس بات پر بھروسہ کرتا ہے کہ جب تک اس کے لیے کنٹریکٹ کا پتہ وہی رہتا ہے، اس میں کوئی تبدیلی نہیں آتی ہے۔ اگر کلائنٹ پر تصدیق کی جاتی، تو آپ کو ہر بار کلائنٹ ڈاؤن لوڈ کرنے پر موصول ہونے والے کوڈ کی تصدیق کرنی پڑتی۔
نیز، جبکہ یہ گیم سنگل پلیئر ہے، بہت سے بلاک چین گیمز ملٹی پلیئر ہیں۔ آن چین تصدیق کا مطلب ہے کہ آپ صرف ایک بار زیرو نالج پروف کی تصدیق کرتے ہیں۔ اسے کلائنٹ میں کرنے کے لیے ہر کلائنٹ کو آزادانہ طور پر تصدیق کرنے کی ضرورت ہوگی۔
نقشے کو TypeScript یا Zokrates میں فلیٹ کریں؟
عام طور پر، جب پروسیسنگ یا تو TypeScript یا Zokrates میں کی جا سکتی ہے، تو اسے TypeScript میں کرنا بہتر ہے، جو بہت تیز ہے، اور زیرو نالج پروف کی ضرورت نہیں ہے۔ یہی وجہ ہے، مثال کے طور پر، کہ ہم Zokrates کو ہیش فراہم نہیں کرتے ہیں اور اسے یہ تصدیق کرنے کے لیے کہتے ہیں کہ یہ درست ہے۔ ہیشنگ کو Zokrates کے اندر کرنا پڑتا ہے، لیکن واپس کیے گئے ہیش اور آن چین ہیش کے درمیان مماثلت اس کے باہر ہو سکتی ہے۔
تاہم، ہم اب بھی Zokrates میں نقشے کو فلیٹ کرتے ہیںopens in a new tab، جبکہ ہم اسے TypeScript میں کر سکتے تھے۔ وجہ یہ ہے کہ دوسرے اختیارات، میری رائے میں، بدتر ہیں۔
-
Zokrates کوڈ کو بولین کی ایک جہتی صف فراہم کریں، اور دو جہتی نقشہ حاصل کرنے کے لیے
x*(height+2) +yجیسے تاثر کا استعمال کریں۔ یہ کوڈopens in a new tab کو قدرے زیادہ پیچیدہ بنا دے گا، لہذا میں نے فیصلہ کیا کہ کارکردگی کا فائدہ ایک ٹیوٹوریل کے لیے اس کے قابل نہیں ہے۔ -
Zokrates کو ایک جہتی صف اور دو جہتی صف دونوں بھیجیں۔ تاہم، اس حل سے ہمیں کچھ حاصل نہیں ہوتا۔ Zokrates کوڈ کو یہ تصدیق کرنی ہوگی کہ اسے فراہم کردہ ایک جہتی صف واقعی دو جہتی صف کی صحیح نمائندگی ہے۔ تو کارکردگی میں کوئی فائدہ نہیں ہوگا۔
-
Zokrates میں دو جہتی صف کو فلیٹ کریں۔ یہ سب سے آسان آپشن ہے، لہذا میں نے اسے منتخب کیا۔
نقشوں کو کہاں اسٹور کریں
اس ایپلیکیشن میں gamesInProgressopens in a new tab صرف میموری میں ایک متغیر ہے۔ اس کا مطلب ہے کہ اگر آپ کا سرور مر جاتا ہے اور اسے دوبارہ شروع کرنے کی ضرورت ہے، تو اس میں محفوظ تمام معلومات ضائع ہو جاتی ہیں۔ نہ صرف کھلاڑی اپنا کھیل جاری رکھنے سے قاصر ہیں، بلکہ وہ نیا کھیل بھی شروع نہیں کر سکتے کیونکہ آن چین جزو سوچتا ہے کہ ان کا ابھی بھی ایک کھیل جاری ہے۔
یہ واضح طور پر ایک پروڈکشن سسٹم کے لیے خراب ڈیزائن ہے، جس میں آپ اس معلومات کو ایک ڈیٹا بیس میں محفوظ کریں گے۔ میں نے یہاں ایک متغیر کا استعمال صرف اس لیے کیا کیونکہ یہ ایک ٹیوٹوریل ہے اور سادگی سب سے اہم غور ہے۔
نتیجہ: کن حالات میں یہ مناسب تکنیک ہے؟
تو، اب آپ جانتے ہیں کہ ایک سرور کے ساتھ ایک گیم کیسے لکھنا ہے جو خفیہ حالت کو اسٹور کرتا ہے جو آن چین سے تعلق نہیں رکھتا۔ لیکن کن معاملات میں آپ کو ایسا کرنا چاہیے؟ دو اہم غور ہیں۔
-
طویل چلنے والا کھیل: جیسا کہ اوپر ذکر کیا گیا ہے، ایک مختصر کھیل میں آپ صرف کھیل ختم ہونے کے بعد حالت کو شائع کر سکتے ہیں اور پھر ہر چیز کی تصدیق کروا سکتے ہیں۔ لیکن یہ ایک آپشن نہیں ہے جب کھیل میں لمبا یا غیر معینہ وقت لگتا ہے، اور حالت کو خفیہ رکھنے کی ضرورت ہے۔
-
کچھ مرکزیت قابل قبول: زیرو نالج پروف سالمیت کی تصدیق کر سکتے ہیں، کہ کوئی ادارہ نتائج کو جعلی نہیں بنا رہا ہے۔ جو وہ نہیں کر سکتے وہ یہ یقینی بنانا ہے کہ ادارہ اب بھی دستیاب ہوگا اور پیغامات کا جواب دے گا۔ ان حالات میں جہاں دستیابی کو بھی غیر مرکزی کرنے کی ضرورت ہے، زیرو نالج پروف ایک کافی حل نہیں ہیں، اور آپ کو ملٹی پارٹی کمپیوٹیشنopens in a new tab کی ضرورت ہے۔
میرے مزید کام کے لیے یہاں دیکھیںopens in a new tab۔
اعترافات
- الوارو الونسو نے اس مضمون کا ایک مسودہ پڑھا اور Zokrates کے بارے میں میری کچھ غلط فہمیوں کو دور کیا۔
کوئی بھی باقی غلطیاں میری ذمہ داری ہیں۔
صفحہ کی آخری تازہ کاری: 6 ستمبر، 2025
