اہم مواد پر جائیں

خفیہ پتوں کا استعمال

خفیہ پتہ
رازداری
کریپٹوگرافی
rust
wasm
متوسط
Ori Pomerantz
30 نومبر، 2025
19 منٹ کی پڑھائی

آپ بل ہیں۔ ان وجوہات کی بنا پر جن میں ہم نہیں جائیں گے، آپ "دنیا کی ملکہ کے لیے ایلس" مہم کو عطیہ دینا چاہتے ہیں اور ایلس کو یہ معلوم کرانا چاہتے ہیں کہ آپ نے عطیہ دیا ہے تاکہ اگر وہ جیت جائے تو وہ آپ کو انعام دے۔ بدقسمتی سے، اس کی جیت کی ضمانت نہیں ہے۔ ایک مسابقتی مہم ہے، "کیرول نظام شمسی کی مہارانی کے لیے"۔ اگر کیرول جیت جاتی ہے، اور اسے پتہ چل جاتا ہے کہ آپ نے ایلس کو عطیہ دیا ہے، تو آپ مشکل میں پڑ جائیں گے۔ لہذا آپ صرف اپنے اکاؤنٹ سے ایلس کے اکاؤنٹ میں 200 ETH منتقل نہیں کر سکتے۔

ERC-5564 (opens in a new tab) کے پاس اس کا حل ہے۔ یہ ERC گمنام منتقلی کے لیے خفیہ پتوں (opens in a new tab) کا استعمال کرنے کا طریقہ بتاتا ہے۔

انتباہ: خفیہ پتوں کے پیچھے کی کریپٹوگرافی، جہاں تک ہم جانتے ہیں، درست ہے۔ تاہم، ممکنہ سائیڈ چینل حملے ہو سکتے ہیں۔ نیچے، آپ دیکھیں گے کہ آپ اس خطرے کو کم کرنے کے لیے کیا کر سکتے ہیں۔

خفیہ پتے کیسے کام کرتے ہیں

یہ مضمون دو طریقوں سے خفیہ پتوں کی وضاحت کرنے کی کوشش کرے گا۔ پہلا یہ ہے کہ ان کا استعمال کیسے کریں۔ یہ حصہ مضمون کے باقی حصے کو سمجھنے کے لیے کافی ہے۔ پھر، اس کے پیچھے ریاضی کی وضاحت ہے۔ اگر آپ کریپٹوگرافی میں دلچسپی رکھتے ہیں، تو یہ حصہ بھی پڑھیں۔

سادہ ورژن (خفیہ پتوں کا استعمال کیسے کریں)

ایلس دو پرائیویٹ کیز بناتی ہے اور متعلقہ پبلک کیز شائع کرتی ہے (جنہیں ایک ہی ڈبل لینتھ میٹا ایڈریس میں ملایا جا سکتا ہے)۔ بل بھی ایک پرائیویٹ کی بناتا ہے اور متعلقہ پبلک کی شائع کرتا ہے۔

ایک پارٹی کی پبلک کی اور دوسری کی پرائیویٹ کی کا استعمال کرتے ہوئے، آپ ایک مشترکہ راز حاصل کر سکتے ہیں جو صرف ایلس اور بل کو معلوم ہے (اسے صرف پبلک کیز سے حاصل نہیں کیا جا سکتا)۔ اس مشترکہ راز کا استعمال کرتے ہوئے، بل خفیہ پتہ حاصل کرتا ہے اور اس پر اثاثے بھیج سکتا ہے۔

ایلس کو بھی مشترکہ راز سے پتہ ملتا ہے، لیکن چونکہ وہ اپنی شائع کردہ پبلک کیز کی پرائیویٹ کیز جانتی ہے، اس لیے وہ وہ پرائیویٹ کی بھی حاصل کر سکتی ہے جو اسے اس پتے سے رقم نکالنے دیتی ہے۔

ریاضی (خفیہ پتے اس طرح کیوں کام کرتے ہیں)

معیاری خفیہ پتے کم کی بٹس کے ساتھ بہتر کارکردگی حاصل کرنے کے لیے الیپٹک کرو کریپٹوگرافی (ECC) (opens in a new tab) کا استعمال کرتے ہیں، جبکہ سیکیورٹی کی سطح وہی رہتی ہے۔ لیکن زیادہ تر ہم اسے نظر انداز کر سکتے ہیں اور یہ دکھاوا کر سکتے ہیں کہ ہم باقاعدہ ریاضی کا استعمال کر رہے ہیں۔

ایک نمبر ہے جسے ہر کوئی جانتا ہے، G۔ آپ G سے ضرب دے سکتے ہیں۔ لیکن ECC کی نوعیت کی وجہ سے، G سے تقسیم کرنا عملی طور پر ناممکن ہے۔ Ethereum میں پبلک کی کریپٹوگرافی عام طور پر جس طرح کام کرتی ہے وہ یہ ہے کہ آپ ایک پرائیویٹ کی، Ppriv، کا استعمال لین دین پر دستخط کرنے کے لیے کر سکتے ہیں جن کی تصدیق پھر ایک پبلک کی، Ppub = GPpriv سے ہوتی ہے۔

ایلس دو پرائیویٹ کیز بناتی ہے، Kpriv اور Vpriv۔ Kpriv کا استعمال خفیہ پتے سے رقم خرچ کرنے کے لیے کیا جائے گا، اور Vpriv کا استعمال ایلس سے تعلق رکھنے والے پتوں کو دیکھنے کے لیے کیا جائے گا۔ ایلس پھر پبلک کیز شائع کرتی ہے: Kpub = GKpriv اور Vpub = GVpriv

بل ایک تیسری پرائیویٹ کی، Rpriv بناتا ہے، اور Rpub = GRpriv کو ایک مرکزی رجسٹری میں شائع کرتا ہے (بل اسے ایلس کو بھی بھیج سکتا تھا، لیکن ہم فرض کرتے ہیں کہ کیرول سن رہی ہے)۔

بل RprivVpub = GRprivVpriv کا حساب لگاتا ہے، جس کی وہ توقع کرتا ہے کہ ایلس بھی جانتی ہے (نیچے وضاحت کی گئی ہے)۔ اس قدر کو S، یعنی مشترکہ راز کہا جاتا ہے۔ یہ بل کو ایک پبلک کی دیتا ہے، Ppub = Kpub+G*hash(S)۔ اس پبلک کی سے، وہ ایک پتہ کا حساب لگا سکتا ہے اور جو بھی وسائل وہ چاہے اسے بھیج سکتا ہے۔ مستقبل میں، اگر ایلس جیت جاتی ہے، تو بل اسے Rpriv بتا سکتا ہے تاکہ یہ ثابت ہو سکے کہ وسائل اسی کی طرف سے آئے ہیں۔

ایلس RpubVpriv = GRprivVpriv کا حساب لگاتی ہے۔ یہ اسے وہی مشترکہ راز، S دیتا ہے۔ چونکہ وہ پرائیویٹ کی، Kpriv جانتی ہے، وہ Ppriv = Kpriv+hash(S) کا حساب لگا سکتی ہے۔ یہ کی اسے اس پتے میں موجود اثاثوں تک رسائی دیتی ہے جو Ppub = GPpriv = GKpriv+G*hash(S) = Kpub+G*hash(S) سے حاصل ہوتا ہے۔

ہمارے پاس ایک علیحدہ ویونگ کی ہے تاکہ ایلس ڈیو کی ورلڈ ڈومینیشن کمپین سروسز کو سب کنٹریکٹ دے سکے۔ ایلس ڈیو کو عوامی پتے بتانے اور جب مزید رقم دستیاب ہو تو اسے مطلع کرنے کے لیے تیار ہے، لیکن وہ نہیں چاہتی کہ وہ اس کی مہم کی رقم خرچ کرے۔

چونکہ دیکھنے اور خرچ کرنے کے لیے علیحدہ کیز کا استعمال ہوتا ہے، ایلس ڈیو کو Vpriv دے سکتی ہے۔ پھر ڈیو S = RpubVpriv = GRprivVpriv کا حساب لگا سکتا ہے اور اس طرح پبلک کیز (Ppub = Kpub+G*hash(S)) حاصل کر سکتا ہے۔ لیکن Kpriv کے بغیر ڈیو پرائیویٹ کی حاصل نہیں کر سکتا۔

خلاصہ یہ کہ، یہ وہ اقدار ہیں جو مختلف شرکاء کو معلوم ہیں۔

ایلسشائع شدہبلڈیو
GGGG
Kpriv۔۔۔
Vpriv۔۔Vpriv
Kpub = GKprivKpubKpubKpub
Vpub = GVprivVpubVpubVpub
۔۔Rpriv۔
RpubRpubRpub = GRprivRpub
S = RpubVpriv = GRprivVpriv۔S = RprivVpub = GRprivVprivS = RpubVpriv = GRprivVpriv
Ppub = Kpub+G*hash(S)۔Ppub = Kpub+G*hash(S)Ppub = Kpub+G*hash(S)
پتہ=f(Ppub)۔پتہ=f(Ppub)پتہ=f(Ppub)پتہ=f(Ppub)
Ppriv = Kpriv+hash(S)۔۔۔

جب خفیہ پتے غلط ہو جاتے ہیں

بلاک چین پر کوئی راز نہیں ہوتے۔ جبکہ خفیہ پتے آپ کو رازداری فراہم کر سکتے ہیں، لیکن وہ رازداری ٹریفک کے تجزیے کے لیے حساس ہے۔ ایک معمولی مثال کے طور پر، تصور کریں کہ بل ایک پتے کو فنڈ کرتا ہے اور فوری طور پر Rpub قدر شائع کرنے کے لیے ایک لین دین بھیجتا ہے۔ ایلس کی Vpriv کے بغیر، ہم یقینی طور پر نہیں کہہ سکتے کہ یہ ایک خفیہ پتہ ہے، لیکن شرط لگانے کا یہی طریقہ ہے۔ پھر، ہم ایک اور لین دین دیکھتے ہیں جو اس پتے سے تمام ETH کو ایلس کے مہم کے فنڈ کے پتے پر منتقل کرتا ہے۔ ہم شاید اسے ثابت نہ کر سکیں، لیکن امکان ہے کہ بل نے ابھی ایلس کی مہم کو عطیہ دیا ہے۔ کیرول یقینی طور پر ایسا ہی سوچے گی۔

بل کے لیے Rpub کی اشاعت کو خفیہ پتے کی فنڈنگ سے الگ کرنا آسان ہے (انہیں مختلف اوقات میں، مختلف پتوں سے کریں)۔ تاہم، یہ ناکافی ہے۔ کیرول جس پیٹرن کو تلاش کرتی ہے وہ یہ ہے کہ بل ایک پتے کو فنڈ کرتا ہے، اور پھر ایلس کا مہم فنڈ اس سے رقم نکالتا ہے۔

ایک حل یہ ہے کہ ایلس کی مہم براہ راست رقم نہ نکالے، بلکہ اسے کسی تیسرے فریق کو ادائیگی کے لیے استعمال کرے۔ اگر ایلس کی مہم ڈیو کی ورلڈ ڈومینیشن کمپین سروسز کو 10 ETH بھیجتی ہے، تو کیرول کو صرف یہ معلوم ہوتا ہے کہ بل نے ڈیو کے صارفین میں سے کسی ایک کو عطیہ دیا ہے۔ اگر ڈیو کے پاس کافی گاہک ہیں، تو کیرول یہ نہیں جان پائے گی کہ بل نے ایلس کو عطیہ دیا جو اس سے مقابلہ کرتی ہے، یا ایڈم، البرٹ، یا ابیگیل کو جن کی کیرول کو پرواہ نہیں ہے۔ ایلس ادائیگی کے ساتھ ایک ہیش شدہ قدر شامل کر سکتی ہے، اور پھر ڈیو کو پری امیج فراہم کر سکتی ہے، تاکہ یہ ثابت ہو سکے کہ یہ اس کا عطیہ تھا۔ متبادل کے طور پر، جیسا کہ اوپر بتایا گیا ہے، اگر ایلس ڈیو کو اپنی Vpriv دیتی ہے، تو وہ پہلے ہی جانتا ہے کہ ادائیگی کس کی طرف سے آئی ہے۔

اس حل کے ساتھ بنیادی مسئلہ یہ ہے کہ اس میں ایلس کو رازداری کا خیال رکھنے کی ضرورت ہوتی ہے جبکہ اس رازداری سے بل کو فائدہ ہوتا ہے۔ ایلس اپنی ساکھ برقرار رکھنا چاہ سکتی ہے تاکہ بل کا دوست باب بھی اسے عطیہ دے۔ لیکن یہ بھی ممکن ہے کہ اسے بل کو بے نقاب کرنے میں کوئی اعتراض نہ ہو، کیونکہ پھر اسے ڈر ہوگا کہ اگر کیرول جیت گئی تو کیا ہوگا۔ بل شاید ایلس کو اور بھی زیادہ مدد فراہم کرے۔

متعدد خفیہ پرتوں کا استعمال

بل کی رازداری کو برقرار رکھنے کے لیے ایلس پر انحصار کرنے کے بجائے، بل خود یہ کر سکتا ہے۔ وہ فرضی لوگوں، باب اور بیلا کے لیے متعدد میٹا پتے بنا سکتا ہے۔ بل پھر باب کو ETH بھیجتا ہے، اور "باب" (جو دراصل بل ہے) اسے بیلا کو بھیجتا ہے۔ "بیلا" (جو بھی بل ہے) اسے ایلس کو بھیجتی ہے۔

کیرول اب بھی ٹریفک کا تجزیہ کر سکتی ہے اور بل-ٹو-باب-ٹو-بیلا-ٹو-ایلس پائپ لائن دیکھ سکتی ہے۔ تاہم، اگر "باب" اور "بیلا" بھی دیگر مقاصد کے لیے ETH کا استعمال کرتے ہیں، تو یہ ظاہر نہیں ہوگا کہ بل نے ایلس کو کچھ بھی منتقل کیا ہے، چاہے ایلس فوری طور پر خفیہ پتے سے اپنے معلوم مہم کے پتے پر رقم نکال لے۔

خفیہ پتے والی ایپلیکیشن لکھنا

یہ مضمون GitHub پر دستیاب ایک خفیہ پتے والی ایپلیکیشن (opens in a new tab) کی وضاحت کرتا ہے۔

ٹولز

ایک ٹائپ اسکرپٹ خفیہ پتہ لائبریری (opens in a new tab) ہے جسے ہم استعمال کر سکتے ہیں۔ تاہم، کریپٹوگرافک آپریشنز CPU-انٹینسیو ہو سکتے ہیں۔ میں انہیں ایک کمپائلڈ زبان، جیسے Rust (opens in a new tab) میں نافذ کرنے کو ترجیح دیتا ہوں، اور براؤزر میں کوڈ چلانے کے لیے WASM (opens in a new tab) کا استعمال کرتا ہوں۔

ہم Vite (opens in a new tab) اور React (opens in a new tab) کا استعمال کرنے جا رہے ہیں۔ یہ انڈسٹری کے معیاری ٹولز ہیں؛ اگر آپ ان سے واقف نہیں ہیں، تو آپ یہ ٹیوٹوریل استعمال کر سکتے ہیں۔ Vite استعمال کرنے کے لیے، ہمیں Node کی ضرورت ہے۔

خفیہ پتوں کو عمل میں دیکھیں

  1. ضروری ٹولز انسٹال کریں: Rust (opens in a new tab) اور Node (opens in a new tab)۔

  2. GitHub ریپوزٹری کو کلون کریں۔

    1git clone https://github.com/qbzzt/251022-stealth-addresses.git
    2cd 251022-stealth-addresses
  3. پیشگی شرائط انسٹال کریں اور Rust کوڈ کو کمپائل کریں۔

    1cd src/rust-wasm
    2rustup target add wasm32-unknown-unknown
    3cargo install wasm-pack
    4wasm-pack build --target web
  4. ویب سرور شروع کریں۔

    1cd ../..
    2npm install
    3npm run dev
  5. ایپلیکیشن (opens in a new tab) پر براؤز کریں۔ اس ایپلیکیشن پیج میں دو فریم ہیں: ایک ایلس کے یوزر انٹرفیس کے لیے اور دوسرا بل کے لیے۔ دونوں فریم آپس میں بات چیت نہیں کرتے؛ وہ صرف سہولت کے لیے ایک ہی صفحے پر ہیں۔

  6. ایلس کے طور پر، ایک خفیہ میٹا ایڈریس بنائیں پر کلک کریں۔ یہ نیا خفیہ پتہ اور متعلقہ پرائیویٹ کیز دکھائے گا۔ خفیہ میٹا ایڈریس کو کلپ بورڈ پر کاپی کریں۔

  7. بل کے طور پر، نیا خفیہ میٹا ایڈریس پیسٹ کریں اور ایک پتہ بنائیں پر کلک کریں۔ یہ آپ کو ایلس کے لیے فنڈ کرنے کا پتہ دیتا ہے۔

  8. پتہ اور بل کی پبلک کی کاپی کریں اور انہیں ایلس کے یوزر انٹرفیس کے "بل کے ذریعے بنائے گئے پتے کے لیے پرائیویٹ کی" والے حصے میں پیسٹ کریں۔ ایک بار جب وہ فیلڈز بھر جائیں گے، تو آپ اس پتے پر اثاثوں تک رسائی کے لیے پرائیویٹ کی دیکھیں گے۔

  9. آپ ایک آن لائن کیلکولیٹر (opens in a new tab) کا استعمال کر سکتے ہیں تاکہ یہ یقینی بنایا جا سکے کہ پرائیویٹ کی پتے سے مطابقت رکھتی ہے۔

پروگرام کیسے کام کرتا ہے

WASM جزو

وہ سورس کوڈ جو WASM میں کمپائل ہوتا ہے Rust (opens in a new tab) میں لکھا گیا ہے۔ آپ اسے src/rust_wasm/src/lib.rs (opens in a new tab) میں دیکھ سکتے ہیں۔ یہ کوڈ بنیادی طور پر جاوا اسکرپٹ کوڈ اور eth-stealth-addresses لائبریری (opens in a new tab) کے درمیان ایک انٹرفیس ہے۔

Cargo.toml

Rust میں Cargo.toml (opens in a new tab) جاوا اسکرپٹ میں package.json (opens in a new tab) کے مترادف ہے۔ اس میں پیکیج کی معلومات، انحصاری اعلانات وغیرہ شامل ہیں۔

1[package]
2name = "rust-wasm"
3version = "0.1.0"
4edition = "2024"
5
6[dependencies]
7eth-stealth-addresses = "0.1.0"
8hex = "0.4.3"
9wasm-bindgen = "0.2.104"
10getrandom = { version = "0.2", features = ["js"] }
سب دکھائیں

getrandom (opens in a new tab) پیکیج کو بے ترتیب اقدار پیدا کرنے کی ضرورت ہے۔ یہ خالص الگورتھمک طریقوں سے نہیں کیا جا سکتا؛ اسے اینٹروپی کے منبع کے طور پر ایک طبعی عمل تک رسائی کی ضرورت ہوتی ہے۔ یہ تعریف بتاتی ہے کہ ہم اس اینٹروپی کو اس براؤزر سے پوچھ کر حاصل کریں گے جس میں ہم چل رہے ہیں۔

1console_error_panic_hook = "0.1.7"

یہ لائبریری (opens in a new tab) ہمیں مزید معنی خیز غلطی کے پیغامات دیتی ہے جب WASM کوڈ پینک کرتا ہے اور جاری نہیں رہ سکتا۔

1[lib]
2crate-type = ["cdylib", "rlib"]

WASM کوڈ تیار کرنے کے لیے درکار آؤٹ پٹ قسم۔

lib.rs

یہ اصل Rust کوڈ ہے۔

1use wasm_bindgen::prelude::*;

Rust سے WASM پیکیج بنانے کی تعریفیں۔ وہ یہاں (opens in a new tab) دستاویزی ہیں۔

1use eth_stealth_addresses::{
2 generate_stealth_meta_address,
3 generate_stealth_address,
4 compute_stealth_key
5};

وہ فنکشنز جن کی ہمیں eth-stealth-addresses لائبریری (opens in a new tab) سے ضرورت ہے۔

1use hex::{decode,encode};

Rust عام طور پر اقدار کے لیے بائٹ ایریز (opens in a new tab) ([u8; <size>]) کا استعمال کرتا ہے۔ لیکن جاوا اسکرپٹ میں، ہم عام طور پر ہیکسا ڈیسیمل اسٹرنگز کا استعمال کرتے ہیں۔ ہیکس لائبریری (opens in a new tab) ہمارے لیے ایک نمائندگی سے دوسری میں ترجمہ کرتی ہے۔

1#[wasm_bindgen]

جاوا اسکرپٹ سے اس فنکشن کو کال کرنے کے قابل ہونے کے لیے WASM بائنڈنگز بنائیں۔

1pub fn wasm_generate_stealth_meta_address() -> String {

متعدد فیلڈز والے آبجیکٹ کو واپس کرنے کا سب سے آسان طریقہ JSON اسٹرنگ واپس کرنا ہے۔

1 let (address, spend_private_key, view_private_key) =
2 generate_stealth_meta_address();

generate_stealth_meta_address (opens in a new tab) تین فیلڈز واپس کرتا ہے:

  • میٹا ایڈریس (Kpub اور Vpub)
  • ویونگ پرائیویٹ کی (Vpriv)
  • اسپینڈنگ پرائیویٹ کی (Kpriv)

ٹیوپل (opens in a new tab) سنٹیکس ہمیں ان اقدار کو دوبارہ الگ کرنے دیتا ہے۔

1 format!("{{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}}",
2 encode(address),
3 encode(view_private_key),
4 encode(spend_private_key)
5 )
6}

JSON-انکوڈڈ اسٹرنگ بنانے کے لیے format! (opens in a new tab) میکرو کا استعمال کریں۔ ایریز کو ہیکس اسٹرنگز میں تبدیل کرنے کے لیے hex::encode (opens in a new tab) کا استعمال کریں۔

1fn str_to_array<const N: usize>(s: &str) -> Option<[u8; N]> {

یہ فنکشن ایک ہیکس اسٹرنگ (جو جاوا اسکرپٹ کے ذریعے فراہم کی گئی ہے) کو بائٹ ایرے میں بدل دیتا ہے۔ ہم اسے جاوا اسکرپٹ کوڈ کے ذریعے فراہم کردہ اقدار کو پارس کرنے کے لیے استعمال کرتے ہیں۔ یہ فنکشن اس لیے پیچیدہ ہے کہ Rust ایریز اور ویکٹرز کو کیسے ہینڈل کرتا ہے۔

<const N: usize> ایکسپریشن کو جینرک (opens in a new tab) کہا جاتا ہے۔ N ایک پیرامیٹر ہے جو واپس آنے والی ایرے کی لمبائی کو کنٹرول کرتا ہے۔ فنکشن کو دراصل str_to_array::<n> کہا جاتا ہے، جہاں n ایرے کی لمبائی ہے۔

واپسی کی قدر Option<[u8; N]> ہے، جس کا مطلب ہے کہ واپس آنے والی ایرے اختیاری (opens in a new tab) ہے۔ یہ Rust میں ان فنکشنز کے لیے ایک عام پیٹرن ہے جو ناکام ہو سکتے ہیں۔

مثال کے طور پر، اگر ہم str_to_array::10("bad060a7") کو کال کرتے ہیں، تو فنکشن کو دس-ویلیو ایرے واپس کرنا چاہیے، لیکن ان پٹ صرف چار بائٹس ہے۔ فنکشن کو ناکام ہونے کی ضرورت ہے، اور یہ None واپس کرکے ایسا کرتا ہے۔ str_to_array::4("bad060a7") کے لیے واپسی کی قدر Some<[0xba, 0xd0, 0x60, 0xa7]> ہوگی۔

1 // decode returns Result<Vec<u8>, _>
2 let vec = decode(s).ok()?;

hex::decode (opens in a new tab) فنکشن Result<Vec<u8>, FromHexError> واپس کرتا ہے۔ Result (opens in a new tab) قسم میں یا تو ایک کامیاب نتیجہ (Ok(value)) یا ایک خرابی (Err(error)) ہو سکتی ہے۔

.ok()طریقہResultکو ایکOptionمیں بدل دیتا ہے، جس کی قدر یا تو کامیاب ہونے پرOk()کی قدر ہوتی ہے یاNoneاگر نہیں۔ آخر میں، [سوالیہ نشان آپریٹر](https://doc.rust-lang.org/std/option/#the-question-mark-operator-) موجودہ فنکشنز کو ختم کر دیتا ہے اور اگرOptionخالی ہو توNoneواپس کرتا ہے۔ بصورت دیگر، یہ قدر کو ان ریپ کرتا ہے اور اسے واپس کرتا ہے (اس صورت میں،vec` کو ایک قدر تفویض کرنے کے لیے)۔

یہ غلطیوں کو سنبھالنے کا ایک عجیب و غریب طریقہ لگتا ہے، لیکن Result اور Option اس بات کو یقینی بناتے ہیں کہ تمام غلطیوں کو کسی نہ کسی طریقے سے سنبھالا جائے۔

1 if vec.len() != N { return None; }

اگر بائٹس کی تعداد غلط ہے، تو یہ ایک ناکامی ہے، اور ہم None واپس کرتے ہیں۔

1 // try_into consumes vec and attempts to make [u8; N]
2 let array: [u8; N] = vec.try_into().ok()?;

Rust میں دو ایرے کی قسمیں ہیں۔ ایریز (opens in a new tab) کا ایک مقررہ سائز ہوتا ہے۔ ویکٹرز (opens in a new tab) بڑھ اور سکڑ سکتے ہیں۔ hex::decode ایک ویکٹر واپس کرتا ہے، لیکن eth_stealth_addresses لائبریری ایریز وصول کرنا چاہتی ہے۔ .try_into() (opens in a new tab) ایک قدر کو دوسری قسم میں تبدیل کرتا ہے، مثال کے طور پر، ایک ویکٹر کو ایک ایرے میں۔

1 Some(array)
2}

Rust کو فنکشن کے آخر میں قدر واپس کرتے وقت return (opens in a new tab) کلیدی لفظ استعمال کرنے کی ضرورت نہیں ہوتی۔

1#[wasm_bindgen]
2pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option<String> {

یہ فنکشن ایک پبلک میٹا ایڈریس وصول کرتا ہے، جس میں Vpub اور Kpub دونوں شامل ہیں۔ یہ خفیہ پتہ، شائع کرنے کے لیے پبلک کی (Rpub)، اور ایک بائٹ کی اسکین ویلیو واپس کرتا ہے جو اس شناخت کو تیز کرتی ہے کہ کون سے شائع شدہ پتے ایلس سے تعلق رکھتے ہیں۔

اسکین ویلیو مشترکہ راز (S = GRprivVpriv) کا حصہ ہے۔ یہ قدر ایلس کو دستیاب ہے، اور اسے چیک کرنا اس بات کی جانچ سے بہت تیز ہے کہ آیا f(Kpub+G*hash(S)) شائع شدہ پتے کے برابر ہے۔

1 let (address, r_pub, scan) =
2 generate_stealth_address(&str_to_array::<66>(stealth_address)?);

ہم لائبریری کے generate_stealth_address (opens in a new tab) کا استعمال کرتے ہیں۔

1 format!("{{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}}",
2 encode(address),
3 encode(r_pub),
4 encode(&[scan])
5 ).into()
6}

JSON-انکوڈڈ آؤٹ پٹ اسٹرنگ تیار کریں۔

1#[wasm_bindgen]
2pub fn wasm_compute_stealth_key(
3 address: &str,
4 bill_pub_key: &str,
5 view_private_key: &str,
6 spend_private_key: &str
7) -> Option<String> {
8 .
9 .
10 .
11}
سب دکھائیں

یہ فنکشن لائبریری کے compute_stealth_key (opens in a new tab) کا استعمال کرتا ہے تاکہ پتے (Rpriv) سے رقم نکالنے کے لیے پرائیویٹ کی کا حساب لگایا جا سکے۔ اس حساب کے لیے ان اقدار کی ضرورت ہے:

  • پتہ (Address=f(Ppub))
  • بل کے ذریعے بنائی گئی پبلک کی (Rpub)
  • ویو پرائیویٹ کی (Vpriv)
  • اسپینڈ پرائیویٹ کی (Kpriv)
1#[wasm_bindgen(start)]

#[wasm_bindgen(start)] (opens in a new tab) بتاتا ہے کہ فنکشن اس وقت عمل میں لایا جاتا ہے جب WASM کوڈ شروع ہوتا ہے۔

1pub fn main() {
2 console_error_panic_hook::set_once();
3}

یہ کوڈ بتاتا ہے کہ پینک آؤٹ پٹ کو جاوا اسکرپٹ کنسول پر بھیجا جائے۔ اسے عمل میں دیکھنے کے لیے، ایپلیکیشن کا استعمال کریں اور بل کو ایک غلط میٹا ایڈریس دیں (صرف ایک ہیکسا ڈیسیمل ہندسہ تبدیل کریں)۔ آپ کو جاوا اسکرپٹ کنسول میں یہ خرابی نظر آئے گی:

1rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9:
2assertion `left == right` failed
3 left: 0
4 right: 1

اس کے بعد ایک اسٹیک ٹریس ہوتا ہے۔ پھر بل کو درست میٹا ایڈریس دیں، اور ایلس کو یا تو غلط پتہ یا غلط پبلک کی دیں۔ آپ کو یہ خرابی نظر آئے گی:

1rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/eth-stealth-addresses-0.1.0/src/lib.rs:78:9:
2keys do not generate stealth address

دوبارہ، اس کے بعد ایک اسٹیک ٹریس ہوتا ہے۔

یوزر انٹرفیس

یوزر انٹرفیس React (opens in a new tab) کا استعمال کرتے ہوئے لکھا گیا ہے اور Vite (opens in a new tab) کے ذریعے پیش کیا جاتا ہے۔ آپ اس ٹیوٹوریل کا استعمال کرتے ہوئے ان کے بارے میں جان سکتے ہیں۔ یہاں WAGMI (opens in a new tab) کی کوئی ضرورت نہیں ہے کیونکہ ہم براہ راست بلاک چین یا والیٹ کے ساتھ تعامل نہیں کرتے ہیں۔

یوزر انٹرفیس کا واحد غیر واضح حصہ WASM کنیکٹیویٹی ہے۔ یہ اس طرح کام کرتا ہے۔

vite.config.js

اس فائل میں Vite کنفیگریشن (opens in a new tab) شامل ہے۔

1import { defineConfig } from 'vite'
2import react from '@vitejs/plugin-react'
3import wasm from "vite-plugin-wasm";
4
5// https://vite.dev/config/
6export default defineConfig({
7 plugins: [react(), wasm()],
8})

ہمیں دو Vite پلگ انز کی ضرورت ہے: react (opens in a new tab) اور wasm (opens in a new tab)۔

App.jsx

یہ فائل ایپلیکیشن کا مرکزی جزو ہے۔ یہ ایک کنٹینر ہے جس میں دو اجزاء شامل ہیں: Alice اور Bill، ان صارفین کے لیے یوزر انٹرفیس۔ WASM کے لیے متعلقہ حصہ انیشیلائزیشن کوڈ ہے۔

1import init from './rust-wasm/pkg/rust_wasm.js'

جب ہم wasm-pack (opens in a new tab) استعمال کرتے ہیں، تو یہ دو فائلیں بناتا ہے جنہیں ہم یہاں استعمال کرتے ہیں: اصل کوڈ کے ساتھ ایک wasm فائل (یہاں، src/rust-wasm/pkg/rust_wasm_bg.wasm) اور اسے استعمال کرنے کی تعریفوں کے ساتھ ایک جاوا اسکرپٹ فائل (یہاں، src/rust_wasm/pkg/rust_wasm.js)۔ اس جاوا اسکرپٹ فائل کا ڈیفالٹ ایکسپورٹ وہ کوڈ ہے جسے WASM شروع کرنے کے لیے چلانے کی ضرورت ہے۔

1function App() {
2 .
3 .
4 .
5 useEffect(() => {
6 const loadWasm = async () => {
7 try {
8 await init();
9 setWasmReady(true)
10 } catch (err) {
11 console.error('Error loading wasm:', err)
12 alert("Wasm error: " + err)
13 }
14 }
15
16 loadWasm()
17 }, []
18 )
سب دکھائیں

useEffect ہک (opens in a new tab) آپ کو ایک فنکشن کی وضاحت کرنے دیتا ہے جو اس وقت عمل میں لایا جاتا ہے جب اسٹیٹ متغیرات تبدیل ہوتے ہیں۔ یہاں، اسٹیٹ متغیرات کی فہرست خالی ہے ([])، لہذا یہ فنکشن صرف ایک بار عمل میں لایا جاتا ہے جب صفحہ لوڈ ہوتا ہے۔

اثر فنکشن کو فوری طور پر واپس آنا ہوتا ہے۔ غیر مطابقت پذیر کوڈ، جیسے WASM init (جسے .wasm فائل لوڈ کرنا پڑتا ہے اور اس لیے وقت لگتا ہے) استعمال کرنے کے لیے ہم ایک اندرونی async (opens in a new tab) فنکشن کی وضاحت کرتے ہیں اور اسے await کے بغیر چلاتے ہیں۔

Bill.jsx

یہ بل کے لیے یوزر انٹرفیس ہے۔ اس کا ایک ہی عمل ہے، ایلس کے ذریعے فراہم کردہ خفیہ میٹا ایڈریس کی بنیاد پر ایک پتہ بنانا۔

1import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js'

ڈیفالٹ ایکسپورٹ کے علاوہ، wasm-pack کے ذریعے تیار کردہ جاوا اسکرپٹ کوڈ WASM کوڈ میں ہر فنکشن کے لیے ایک فنکشن ایکسپورٹ کرتا ہے۔

1 <button onClick={() => {
2 setPublicAddress(JSON.parse(wasm_generate_stealth_address(stealthMetaAddress)))
3 }}>

WASM فنکشنز کو کال کرنے کے لیے، ہم صرف wasm-pack کے ذریعے بنائی گئی جاوا اسکرپٹ فائل کے ذریعے ایکسپورٹ کردہ فنکشن کو کال کرتے ہیں۔

Alice.jsx

Alice.jsx میں کوڈ یکساں ہے، سوائے اس کے کہ ایلس کے دو اعمال ہیں:

  • ایک میٹا ایڈریس بنائیں
  • بل کے ذریعے شائع کردہ پتے کے لیے پرائیویٹ کی حاصل کریں

نتیجہ

خفیہ پتے کوئی تریاق نہیں ہیں؛ انہیں صحیح طریقے سے استعمال کرنا پڑتا ہے۔ لیکن جب صحیح طریقے سے استعمال کیا جائے تو، وہ ایک عوامی بلاک چین پر رازداری کو فعال کر سکتے ہیں۔

میرے مزید کام کے لیے یہاں دیکھیں (opens in a new tab)۔

صفحہ کی آخری تازہ کاری: 14 نومبر، 2025

کیا یہ ٹیوٹوریل کارآمد تھا؟