স্টিলথ এডড্রেস ব্যবহার করা
আপনি হলেন বিল। এমন কিছু কারণে যা আমরা এখানে আলোচনা করব না, আপনি "Alice for Queen of the World" ক্যাম্পেইনে দান করতে চান এবং চান যে অ্যালিস জানুক আপনি দান করেছেন, যাতে সে জিতলে আপনাকে পুরস্কৃত করতে পারে। দুর্ভাগ্যবশত, তার জয় নিশ্চিত নয়। একটি প্রতিযোগী ক্যাম্পেইন রয়েছে, "Carol for Empress of the Solar System"। যদি ক্যারল জেতে এবং সে জানতে পারে যে আপনি অ্যালিসকে দান করেছেন, তবে আপনি সমস্যায় পড়বেন। তাই আপনি কেবল আপনার একাউন্ট থেকে অ্যালিসের একাউন্টে 200 ETH স্থানান্তর করতে পারবেন না।
ERC-5564 (opens in a new tab)-এ এর সমাধান রয়েছে। এই ERC ব্যাখ্যা করে কীভাবে বেনামী স্থানান্তরের জন্য স্টিলথ এডড্রেস (opens in a new tab) ব্যবহার করতে হয়।
সতর্কতা: স্টিলথ এডড্রেসের পেছনের ক্রিপ্টোগ্রাফি, যতদূর আমরা জানি, বেশ মজবুত। তবে, সম্ভাব্য সাইড-চ্যানেল আক্রমণের ঝুঁকি রয়েছে। নিচে, আপনি দেখতে পাবেন কীভাবে এই ঝুঁকি কমানো যায়।
স্টিলথ এডড্রেস কীভাবে কাজ করে
এই নিবন্ধটি দুটি উপায়ে স্টিলথ এডড্রেস ব্যাখ্যা করার চেষ্টা করবে। প্রথমটি হলো কীভাবে এগুলো ব্যবহার করতে হয়। নিবন্ধের বাকি অংশ বোঝার জন্য এই অংশটিই যথেষ্ট। এরপর, এর পেছনের গণিতের একটি ব্যাখ্যা রয়েছে। আপনি যদি ক্রিপ্টোগ্রাফি নিয়ে আগ্রহী হন, তবে এই অংশটিও পড়ুন।
সহজ সংস্করণ (কীভাবে স্টিলথ এডড্রেস ব্যবহার করবেন)
অ্যালিস দুটি প্রাইভেট কি তৈরি করে এবং সংশ্লিষ্ট পাবলিক কি-গুলো প্রকাশ করে (যা একটি একক ডাবল-লেংথ মেটা-এডড্রেসে একত্রিত করা যেতে পারে)। বিলও একটি প্রাইভেট কি তৈরি করে এবং সংশ্লিষ্ট পাবলিক কি প্রকাশ করে।
এক পক্ষের পাবলিক কি এবং অন্য পক্ষের প্রাইভেট কি ব্যবহার করে, আপনি একটি শেয়ার্ড সিক্রেট (shared secret) বের করতে পারেন যা কেবল অ্যালিস এবং বিলের জানা থাকে (এটি কেবল পাবলিক কি থেকে বের করা সম্ভব নয়)। এই শেয়ার্ড সিক্রেট ব্যবহার করে, বিল স্টিলথ এডড্রেস পায় এবং সেখানে সম্পদ পাঠাতে পারে।
অ্যালিসও শেয়ার্ড সিক্রেট থেকে এডড্রেসটি পায়, কিন্তু যেহেতু সে তার প্রকাশিত পাবলিক কি-গুলোর প্রাইভেট কি জানে, তাই সে সেই প্রাইভেট কি-ও পেতে পারে যা তাকে ওই এডড্রেস থেকে সম্পদ উত্তোলনের অনুমতি দেয়।
গণিত (কেন স্টিলথ এডড্রেস এভাবে কাজ করে)
স্ট্যান্ডার্ড স্টিলথ এডড্রেসগুলো এলিপটিক-কার্ভ ক্রিপ্টোগ্রাফি (ECC) (opens in a new tab) ব্যবহার করে যাতে কম কি বিট দিয়ে ভালো পারফরম্যান্স পাওয়া যায়, অথচ একই স্তরের নিরাপত্তা বজায় থাকে। তবে বেশিরভাগ ক্ষেত্রে আমরা এটি এড়িয়ে যেতে পারি এবং ধরে নিতে পারি যে আমরা সাধারণ পাটিগণিত ব্যবহার করছি।
একটি সংখ্যা আছে যা সবাই জানে, G। আপনি G দিয়ে গুণ করতে পারেন। কিন্তু ECC-এর প্রকৃতির কারণে, G দিয়ে ভাগ করা প্রায় অসম্ভব। ইথিরিয়ামে পাবলিক কি ক্রিপ্টোগ্রাফি সাধারণত যেভাবে কাজ করে তা হলো, আপনি একটি প্রাইভেট কি, 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) থেকে তৈরি হয়।
আমাদের একটি আলাদা ভিউয়িং কি (viewing key) রয়েছে যাতে অ্যালিস ডেভস ওয়ার্ল্ড ডমিনেশন ক্যাম্পেইন সার্ভিসেসকে সাবকন্ট্রাক্ট দিতে পারে। অ্যালিস ডেভকে পাবলিক এডড্রেসগুলো জানাতে এবং আরও অর্থ এলে তাকে অবহিত করতে ইচ্ছুক, কিন্তু সে চায় না ডেভ তার ক্যাম্পেইনের অর্থ ব্যয় করুক।
যেহেতু দেখা এবং ব্যয় করার জন্য আলাদা কি ব্যবহার করা হয়, অ্যালিস ডেভকে Vpriv দিতে পারে। তখন ডেভ S = RpubVpriv = GRprivVpriv হিসাব করতে পারে এবং সেভাবে পাবলিক কি-গুলো (Ppub = Kpub+G*hash(S)) পেতে পারে। কিন্তু Kpriv ছাড়া ডেভ প্রাইভেট কি পেতে পারে না।
সংক্ষেপে, এগুলো হলো বিভিন্ন অংশগ্রহণকারীর জানা মান।
| অ্যালিস | প্রকাশিত | বিল | ডেভ |
|---|---|---|---|
| G | G | G | G |
| Kpriv | - | - | - |
| Vpriv | - | - | Vpriv |
| Kpub = GKpriv | Kpub | Kpub | Kpub |
| Vpub = GVpriv | Vpub | Vpub | Vpub |
| - | - | Rpriv | - |
| Rpub | Rpub | Rpub = GRpriv | Rpub |
| S = RpubVpriv = GRprivVpriv | - | S = RprivVpub = GRprivVpriv | S = RpubVpriv = GRprivVpriv |
| Ppub = Kpub+G*hash(S) | - | Ppub = Kpub+G*hash(S) | Ppub = Kpub+G*hash(S) |
| এডড্রেস=f(Ppub) | - | এডড্রেস=f(Ppub) | এডড্রেস=f(Ppub) |
| Ppriv = Kpriv+hash(S) | - | - | - |
যখন স্টিলথ এডড্রেস ভুল পথে যায়
ব্লকচেইনে কোনো গোপনীয়তা নেই। যদিও স্টিলথ এডড্রেস আপনাকে গোপনীয়তা প্রদান করতে পারে, সেই গোপনীয়তা ট্রাফিক বিশ্লেষণের জন্য সংবেদনশীল। একটি সাধারণ উদাহরণ হিসেবে, কল্পনা করুন যে বিল একটি এডড্রেসে ফান্ড দেয় এবং সাথে সাথে একটি Rpub মান প্রকাশ করার জন্য একটি লেনদেন পাঠায়। অ্যালিসের Vpriv ছাড়া, আমরা নিশ্চিত হতে পারি না যে এটি একটি স্টিলথ এডড্রেস, তবে এটি হওয়ার সম্ভাবনাই বেশি। এরপর, আমরা আরেকটি লেনদেন দেখি যা সেই এডড্রেস থেকে সমস্ত ETH অ্যালিসের ক্যাম্পেইন ফান্ড এডড্রেসে স্থানান্তর করে। আমরা হয়তো এটি প্রমাণ করতে পারব না, তবে সম্ভবত বিল এইমাত্র অ্যালিসের ক্যাম্পেইনে দান করেছে। ক্যারল অবশ্যই এমনটাই ভাববে।
বিলের জন্য Rpub প্রকাশ করা এবং স্টিলথ এডড্রেসে ফান্ড দেওয়া আলাদা করা সহজ (ভিন্ন সময়ে, ভিন্ন এডড্রেস থেকে এগুলো করা)। তবে, এটি যথেষ্ট নয়। ক্যারল যে প্যাটার্নটি খুঁজছে তা হলো বিল একটি এডড্রেসে ফান্ড দেয় এবং তারপর অ্যালিসের ক্যাম্পেইন ফান্ড সেখান থেকে তা তুলে নেয়।
এর একটি সমাধান হলো অ্যালিসের ক্যাম্পেইন সরাসরি অর্থ উত্তোলন না করে, এটি কোনো তৃতীয় পক্ষকে অর্থ প্রদানের জন্য ব্যবহার করা। যদি অ্যালিসের ক্যাম্পেইন ডেভস ওয়ার্ল্ড ডমিনেশন ক্যাম্পেইন সার্ভিসেসকে 10 ETH পাঠায়, তবে ক্যারল কেবল জানবে যে বিল ডেভের কোনো একজন গ্রাহককে দান করেছে। যদি ডেভের পর্যাপ্ত গ্রাহক থাকে, তবে ক্যারল জানতে পারবে না যে বিল তার প্রতিযোগী অ্যালিসকে দান করেছে, নাকি অ্যাডাম, অ্যালবার্ট বা অ্যাবিগেলকে দান করেছে যাদের নিয়ে ক্যারলের কোনো মাথাব্যথা নেই। অ্যালিস পেমেন্টের সাথে একটি হ্যাশ করা মান যুক্ত করতে পারে এবং তারপর ডেভকে প্রিইমেজ (preimage) প্রদান করতে পারে, এটি প্রমাণ করতে যে এটি তার দান ছিল। বিকল্পভাবে, যেমনটি উপরে উল্লেখ করা হয়েছে, যদি অ্যালিস ডেভকে তার Vpriv দেয়, তবে সে আগে থেকেই জানে পেমেন্টটি কার কাছ থেকে এসেছে।
এই সমাধানের প্রধান সমস্যা হলো এর জন্য অ্যালিসকে গোপনীয়তার বিষয়ে যত্নশীল হতে হবে যখন সেই গোপনীয়তা বিলের উপকারে আসে। অ্যালিস হয়তো তার সুনাম বজায় রাখতে চাইতে পারে যাতে বিলের বন্ধু ববও তাকে দান করে। তবে এটাও সম্ভব যে সে বিলকে প্রকাশ করতে আপত্তি করবে না, কারণ তখন বিল ভয় পাবে যে ক্যারল জিতলে কী হবে। এর ফলে বিল হয়তো অ্যালিসকে আরও বেশি সমর্থন প্রদান করবে।
একাধিক স্টিলথ লেয়ার ব্যবহার করা
বিলের গোপনীয়তা রক্ষার জন্য অ্যালিসের ওপর নির্ভর করার পরিবর্তে, বিল নিজেই এটি করতে পারে। সে কাল্পনিক ব্যক্তি বব এবং বেলার জন্য একাধিক মেটা-এডড্রেস তৈরি করতে পারে। এরপর বিল ববকে ETH পাঠায় এবং "বব" (যে আসলে বিল) তা বেলাকে পাঠায়। "বেলা" (সেও বিল) তা অ্যালিসকে পাঠায়।
ক্যারল এখনও ট্রাফিক বিশ্লেষণ করতে পারে এবং বিল-থেকে-বব-থেকে-বেলা-থেকে-অ্যালিস পাইপলাইন দেখতে পারে। তবে, যদি "বব" এবং "বেলা" অন্যান্য উদ্দেশ্যেও ETH ব্যবহার করে, তবে মনে হবে না যে বিল অ্যালিসকে কিছু স্থানান্তর করেছে, এমনকি যদি অ্যালিস সাথে সাথে স্টিলথ এডড্রেস থেকে তার পরিচিত ক্যাম্পেইন এডড্রেসে অর্থ তুলে নেয়।
একটি স্টিলথ-এডড্রেস অ্যাপ্লিকেশন লেখা
এই নিবন্ধটি একটি স্টিলথ-এডড্রেস অ্যাপ্লিকেশন ব্যাখ্যা করে যা GitHub-এ উপলব্ধ (opens in a new tab)।
টুলস
একটি টাইপস্ক্রিপ্ট স্টিলথ এডড্রেস লাইব্রেরি (opens in a new tab) রয়েছে যা আমরা ব্যবহার করতে পারতাম। তবে, ক্রিপ্টোগ্রাফিক অপারেশনগুলো সিপিইউ-নিবিড় (CPU-intensive) হতে পারে। আমি এগুলোকে একটি কম্পাইলড ভাষা, যেমন 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 প্রয়োজন।
স্টিলথ এডড্রেসগুলো কীভাবে কাজ করে তা দেখুন
-
প্রয়োজনীয় টুলস ইনস্টল করুন: Rust (opens in a new tab) এবং Node (opens in a new tab)।
-
GitHub রিপোজিটরি ক্লোন করুন।
1git clone https://github.com/qbzzt/251022-stealth-addresses.git2cd 251022-stealth-addresses -
পূর্বশর্তগুলো ইনস্টল করুন এবং Rust কোড কম্পাইল করুন।
1cd src/rust-wasm2rustup target add wasm32-unknown-unknown3cargo install wasm-pack4wasm-pack build --target web -
ওয়েব সার্ভার চালু করুন।
1cd ../..2npm install3npm run dev -
অ্যাপ্লিকেশনটিতে (opens in a new tab) ব্রাউজ করুন। এই অ্যাপ্লিকেশন পেজে দুটি ফ্রেম রয়েছে: একটি অ্যালিসের ইউজার ইন্টারফেসের জন্য এবং অন্যটি বিলের জন্য। ফ্রেম দুটি একে অপরের সাথে যোগাযোগ করে না; সুবিধার জন্য এগুলো কেবল একই পেজে রাখা হয়েছে।
-
অ্যালিস হিসেবে, Generate a Stealth Meta-Address-এ ক্লিক করুন। এটি নতুন স্টিলথ এডড্রেস এবং সংশ্লিষ্ট প্রাইভেট কি-গুলো প্রদর্শন করবে। স্টিলথ মেটা-এডড্রেসটি ক্লিপবোর্ডে কপি করুন।
-
বিল হিসেবে, নতুন স্টিলথ মেটা-এডড্রেসটি পেস্ট করুন এবং Generate an address-এ ক্লিক করুন। এটি আপনাকে অ্যালিসের জন্য ফান্ড দেওয়ার এডড্রেসটি দেবে।
-
এডড্রেস এবং বিলের পাবলিক কি কপি করুন এবং অ্যালিসের ইউজার ইন্টারফেসের "Private key for address generated by Bill" অংশে পেস্ট করুন। এই ফিল্ডগুলো পূরণ হয়ে গেলে, আপনি সেই এডড্রেসের সম্পদে অ্যাক্সেস করার প্রাইভেট কি দেখতে পাবেন।
-
প্রাইভেট কি-টি এডড্রেসের সাথে মিলে কিনা তা নিশ্চিত করতে আপনি একটি অনলাইন ক্যালকুলেটর (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"56[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_key5};eth-stealth-addresses লাইব্রেরি (opens in a new tab) থেকে আমাদের প্রয়োজনীয় ফাংশনগুলো।
1use hex::{decode,encode};Rust সাধারণত মানগুলোর জন্য বাইট অ্যারে (opens in a new tab) ([u8; <size>]) ব্যবহার করে। কিন্তু জাভাস্ক্রিপ্টে, আমরা সাধারণত হেক্সাডেসিমাল স্ট্রিং ব্যবহার করি। hex লাইব্রেরি (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)
টাপল (tuple) (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> এক্সপ্রেশনটিকে একটি জেনেরিক (generic) (opens in a new tab) বলা হয়। N হলো একটি প্যারামিটার যা রিটার্ন করা অ্যারের দৈর্ঘ্য নিয়ন্ত্রণ করে। ফাংশনটিকে আসলে str_to_array::<n> বলা হয়, যেখানে n হলো অ্যারের দৈর্ঘ্য।
রিটার্ন ভ্যালু হলো Option<[u8; N]>, যার মানে রিটার্ন করা অ্যারেটি ঐচ্ছিক (optional) (opens in a new tab)। এটি Rust-এ এমন ফাংশনগুলোর জন্য একটি সাধারণ প্যাটার্ন যা ব্যর্থ হতে পারে।
উদাহরণস্বরূপ, যদি আমরা str_to_array::10("bad060a7") কল করি, তবে ফাংশনটির একটি দশ-মানের অ্যারে রিটার্ন করার কথা, কিন্তু ইনপুটটি কেবল চার বাইটের। ফাংশনটিকে ব্যর্থ হতে হবে, এবং এটি None রিটার্ন করে তা করে। str_to_array::4("bad060a7")-এর রিটার্ন ভ্যালু হবে Some<[0xba, 0xd0, 0x60, 0xa7]>।
1 // ডিকোড 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 হয়। সবশেষে, প্রশ্নবোধক চিহ্ন অপারেটর (opens in a new tab) বর্তমান ফাংশনগুলোকে বাতিল করে এবং Option খালি থাকলে একটি None রিটার্ন করে। অন্যথায়, এটি মানটিকে আনর্যাপ (unwrap) করে এবং তা রিটার্ন করে (এই ক্ষেত্রে, vec-এ একটি মান অ্যাসাইন করতে)।
এটি এররগুলো পরিচালনা করার জন্য একটি অদ্ভুত জটিল পদ্ধতি বলে মনে হতে পারে, তবে Result এবং Option নিশ্চিত করে যে সমস্ত এরর কোনো না কোনোভাবে পরিচালিত হয়।
1 if vec.len() != N { return None; }যদি বাইটের সংখ্যা ভুল হয়, তবে এটি একটি ব্যর্থতা, এবং আমরা None রিটার্ন করি।
1 // try_into vec-কে কনজিউম করে এবং [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}সব দেখানএই ফাংশনটি এডড্রেস থেকে উত্তোলনের জন্য প্রাইভেট কি (Rpriv) হিসাব করতে লাইব্রেরির compute_stealth_key (opens in a new tab) ব্যবহার করে। এই হিসাবের জন্য এই মানগুলোর প্রয়োজন:
- এডড্রেস (এডড্রেস=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` failed3 left: 04 right: 1এরপরে একটি স্ট্যাক ট্রেস (stack trace) থাকবে। তারপর বিলকে বৈধ মেটা-এডড্রেস দিন, এবং অ্যালিসকে হয় একটি অবৈধ এডড্রেস অথবা একটি অবৈধ পাবলিক কি দিন। আপনি এই এররটি দেখতে পাবেন:
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";45// 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 }1516 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)।
পেজ সর্বশেষ আপডেট: ১৪ নভেম্বর, ২০২৫