diff --git a/public/content/translations/bn/developers/tutorials/stealth-addr/index.md b/public/content/translations/bn/developers/tutorials/stealth-addr/index.md new file mode 100644 index 00000000000..6b5b613b6ae --- /dev/null +++ b/public/content/translations/bn/developers/tutorials/stealth-addr/index.md @@ -0,0 +1,443 @@ +--- +title: "স্টেলথ অ্যাড্রেস ব্যবহার করা" +description: "স্টেলথ অ্যাড্রেস ব্যবহারকারীদের বেনামে অ্যাসেট ট্রান্সফার করতে দেয়। এই আর্টিকেলটি পড়ার পর, আপনি সক্ষম হবেন: স্টেলথ অ্যাড্রেস কী এবং কীভাবে এটি কাজ করে তা ব্যাখ্যা করতে, কীভাবে এমনভাবে স্টেলথ অ্যাড্রেস ব্যবহার করতে হয় যা গোপনীয়তা রক্ষা করে তা বুঝতে এবং স্টেলথ অ্যাড্রেস ব্যবহার করে এমন একটি ওয়েব-ভিত্তিক অ্যাপ্লিকেশন লিখতে।" +author: Ori Pomerantz +tags: + [ + "স্টেলথ অ্যাড্রেস", + "গোপনীয়তা", + "ক্রিপ্টোগ্রাফি", + "rust", + "wasm" + ] +skill: intermediate +published: 2025-11-30 +lang: bn +sidebarDepth: 3 +--- + +আপনি বিল। আমরা যে কারণগুলিতে যাব না, সেগুলির জন্য আপনি "বিশ্বের রানীর জন্য অ্যালিস" প্রচারাভিযানে অনুদান দিতে চান এবং অ্যালিসকে জানাতে চান যে আপনি অনুদান দিয়েছেন যাতে সে জিতলে আপনাকে পুরস্কৃত করবে। দুর্ভাগ্যবশত, তার জয় নিশ্চিত নয়। একটি প্রতিযোগী প্রচারাভিযান আছে, "সৌরজগতের সম্রাজ্ঞীর জন্য ক্যারল"। যদি ক্যারল জিতে যায়, এবং সে জানতে পারে যে আপনি অ্যালিসকে অনুদান দিয়েছেন, তাহলে আপনি সমস্যায় পড়বেন। সুতরাং আপনি শুধু আপনার অ্যাকাউন্ট থেকে অ্যালিসের অ্যাকাউন্টে 200 ETH ট্রান্সফার করতে পারবেন না। + +[ERC-5564](https://eips.ethereum.org/EIPS/eip-5564) এর কাছে সমাধান আছে। এই ERC বেনামী ট্রান্সফারের জন্য কীভাবে [স্টেলথ অ্যাড্রেস](https://nerolation.github.io/stealth-utils) ব্যবহার করতে হয় তা ব্যাখ্যা করে। + +**সতর্কতা**: স্টেলথ অ্যাড্রেসের পিছনের ক্রিপ্টোগ্রাফি, যতদূর আমরা জানি, নির্ভরযোগ্য। যাইহোক, সম্ভাব্য সাইড-চ্যানেল অ্যাটাকের ঝুঁকি আছে। [নিচে](#go-wrong), আপনি এই ঝুঁকি কমাতে কী করতে পারেন তা দেখতে পাবেন। + +## স্টেলথ অ্যাড্রেস কীভাবে কাজ করে {#how} + +এই আর্টিকেলটি দুটি উপায়ে স্টেলথ অ্যাড্রেস ব্যাখ্যা করার চেষ্টা করবে। প্রথমটি হলো [কীভাবে সেগুলি ব্যবহার করতে হয়](#how-use)। আর্টিকেলের বাকি অংশ বোঝার জন্য এই অংশটিই যথেষ্ট। তারপরে, [এর পেছনের গণিতের একটি ব্যাখ্যা](#how-math) রয়েছে। আপনি যদি ক্রিপ্টোগ্রাফিতে আগ্রহী হন, তাহলে এই অংশটিও পড়ুন। + +### সরল সংস্করণ (কীভাবে স্টেলথ অ্যাড্রেস ব্যবহার করবেন) {#how-use} + +অ্যালিস দুটি প্রাইভেট কী তৈরি করে এবং সংশ্লিষ্ট পাবলিক কীগুলি প্রকাশ করে (যা একটি একক ডাবল-লেংথ মেটা-অ্যাড্রেসে একত্রিত করা যেতে পারে)। বিলও একটি প্রাইভেট কী তৈরি করে এবং সংশ্লিষ্ট পাবলিক কী প্রকাশ করে। + +এক পক্ষের পাবলিক কী এবং অন্য পক্ষের প্রাইভেট কী ব্যবহার করে, আপনি একটি শেয়ার্ড সিক্রেট পেতে পারেন যা শুধুমাত্র অ্যালিস এবং বিল জানে (এটি শুধুমাত্র পাবলিক কী থেকে পাওয়া যায় না)। এই শেয়ার্ড সিক্রেট ব্যবহার করে, বিল স্টেলথ অ্যাড্রেসটি পায় এবং এতে অ্যাসেট পাঠাতে পারে। + +অ্যালিসও শেয়ার্ড সিক্রেট থেকে অ্যাড্রেসটি পায়, কিন্তু যেহেতু সে তার প্রকাশিত পাবলিক কী-এর প্রাইভেট কীগুলি জানে, তাই সে সেই প্রাইভেট কীও পেতে পারে যা তাকে সেই অ্যাড্রেস থেকে উইথড্র করতে দেয়। + +### গণিত (কেন স্টেলথ অ্যাড্রেস এইভাবে কাজ করে) {#how-math} + +স্ট্যান্ডার্ড স্টেলথ অ্যাড্রেসগুলি [ইলিপটিক-কার্ভ ক্রিপ্টোগ্রাফি (ECC)](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/#elliptic-curves-building-blocks-of-a-better-trapdoor) ব্যবহার করে কম কী বিট দিয়ে উন্নত পারফরম্যান্স পেতে, এবং একই স্তরের নিরাপত্তা বজায় রাখে। কিন্তু বেশিরভাগ ক্ষেত্রে আমরা এটিকে উপেক্ষা করতে পারি এবং ভান করতে পারি যে আমরা সাধারণ পাটিগণিত ব্যবহার করছি। + +একটি সংখ্যা আছে যা সবাই জানে, _G_। আপনি _G_ দিয়ে গুণ করতে পারেন। কিন্তু ECC-এর প্রকৃতির কারণে, _G_ দ্বারা ভাগ করা কার্যত অসম্ভব। ইথেরিয়ামে সাধারণত যেভাবে পাবলিক কী ক্রিপ্টোগ্রাফি কাজ করে তা হল, আপনি একটি প্রাইভেট কী, _Ppriv_, ব্যবহার করে ট্রানজ্যাকশন সাইন করতে পারেন যা পরে একটি পাবলিক কী, _Ppub = GPpriv_ দ্বারা ভেরিফাই করা হয়। + +অ্যালিস দুটি প্রাইভেট কী তৈরি করে, _Kpriv_ এবং _Vpriv_। _Kpriv_ স্টেলথ অ্যাড্রেস থেকে অর্থ ব্যয় করতে ব্যবহৃত হবে এবং _Vpriv_ অ্যালিসের মালিকানাধীন অ্যাড্রেসগুলি দেখতে ব্যবহৃত হবে। অ্যালিস তারপর পাবলিক কীগুলি প্রকাশ করে: _Kpub = GKpriv_ এবং _Vpub = GVpriv_ + +বিল একটি তৃতীয় প্রাইভেট কী, _Rpriv_ তৈরি করে এবং _Rpub = GRpriv_ একটি কেন্দ্রীয় রেজিস্ট্রিতে প্রকাশ করে (বিল এটি অ্যালিসকেও পাঠাতে পারত, কিন্তু আমরা ধরে নিচ্ছি ক্যারল শুনছে)। + +বিল _RprivVpub = GRprivVpriv_ গণনা করে, যা সে আশা করে অ্যালিসও জানবে (নিচে ব্যাখ্যা করা হয়েছে)। এই মানটিকে বলা হয় _S_, শেয়ার্ড সিক্রেট। এটি বিলকে একটি পাবলিক কী দেয়, _Ppub = Kpub+G\*হ্যাস(S)_। এই পাবলিক কী থেকে, সে একটি অ্যাড্রেস গণনা করতে পারে এবং সে যা রিসোর্স চায় তা এতে পাঠাতে পারে। ভবিষ্যতে, যদি অ্যালিস জিতে, বিল তাকে _Rpriv_ বলতে পারে প্রমাণ করার জন্য যে রিসোর্সগুলি তার কাছ থেকে এসেছে। + +অ্যালিস _RpubVpriv = GRprivVpriv_ গণনা করে। এটি তাকে একই শেয়ার্ড সিক্রেট, _S_ দেয়। যেহেতু সে প্রাইভেট কী, _Kpriv_ জানে, সে _Ppriv = Kpriv+হ্যাস(S)_ গণনা করতে পারে। এই কী তাকে _Ppub = GPpriv = GKpriv+G\*হ্যাস(S) = Kpub+G\*হ্যাস(S)_ থেকে প্রাপ্ত অ্যাড্রেসে থাকা অ্যাসেট অ্যাক্সেস করতে দেয়। + +আমাদের একটি পৃথক ভিউয়িং কী আছে যা অ্যালিসকে ডেভের ওয়ার্ল্ড ডমিনেশন ক্যাম্পেইন সার্ভিসেস-কে সাবকন্ট্রাক্ট দেওয়ার অনুমতি দেয়। অ্যালিস ডেভকে পাবলিক অ্যাড্রেস জানাতে এবং আরও টাকা পাওয়া গেলে তাকে জানাতে ইচ্ছুক, কিন্তু সে চায় না যে ডেভ তার প্রচারণার টাকা খরচ করুক। + +যেহেতু দেখা এবং খরচ করার জন্য আলাদা কী ব্যবহার করা হয়, অ্যালিস ডেভকে _Vpriv_ দিতে পারে। তারপর ডেভ _S = RpubVpriv = GRprivVpriv_ গণনা করতে পারে এবং সেই উপায়ে পাবলিক কীগুলি পেতে পারে (_Ppub = Kpub+G\*হ্যাস(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\*হ্যাস(S)_ | - | _Ppub = Kpub+G\*হ্যাস(S)_ | _Ppub = Kpub+G\*হ্যাস(S)_ | | +| _অ্যাড্রেস=f(Ppub)_ | - | _অ্যাড্রেস=f(Ppub)_ | _অ্যাড্রেস=f(Ppub)_ | _অ্যাড্রেস=f(Ppub)_ | +| _Ppriv = Kpriv+হ্যাস(S)_ | - | - | - | | + +## যখন স্টেলথ অ্যাড্রেস ভুল হয় {#go-wrong} + +_ব্লকচেইনে কোনো গোপনীয়তা নেই_। যদিও স্টেলথ অ্যাড্রেস আপনাকে গোপনীয়তা দিতে পারে, তবে সেই গোপনীয়তা ট্রাফিক বিশ্লেষণের জন্য ঝুঁকিপূর্ণ। একটি তুচ্ছ উদাহরণ হিসেবে, কল্পনা করুন যে বিল একটি অ্যাড্রেসে ফান্ড করে এবং অবিলম্বে একটি _Rpub_ মান প্রকাশ করার জন্য একটি ট্রানজ্যাকশন পাঠায়। অ্যালিসের _Vpriv_ ছাড়া, আমরা নিশ্চিত হতে পারি না যে এটি একটি স্টেলথ অ্যাড্রেস, কিন্তু এটিই বাজি ধরার উপায়। তারপরে, আমরা আরেকটি ট্রানজ্যাকশন দেখি যা সেই অ্যাড্রেস থেকে সমস্ত ETH অ্যালিসের প্রচারণার ফান্ড অ্যাড্রেসে ট্রান্সফার করে। আমরা হয়তো এটি প্রমাণ করতে পারব না, তবে সম্ভবত বিল সবেমাত্র অ্যালিসের প্রচারণার জন্য অনুদান দিয়েছে। ক্যারল অবশ্যই তাই মনে করবে। + +বিলের জন্য _Rpub_ এর প্রকাশনাটি স্টেলথ অ্যাড্রেসের ফান্ডিং থেকে আলাদা করা সহজ (সেগুলি বিভিন্ন সময়ে, বিভিন্ন অ্যাড্রেস থেকে করা)। তবে, তা যথেষ্ট নয়। ক্যারল যে প্যাটার্নটি খোঁজে তা হল বিল একটি অ্যাড্রেসে ফান্ড করে, এবং তারপর অ্যালিসের প্রচারণার ফান্ড তা থেকে উইথড্র করে। + +একটি সমাধান হল অ্যালিসের প্রচারণার জন্য সরাসরি টাকা উইথড্র না করে, বরং এটি কোনো তৃতীয় পক্ষকে অর্থ প্রদানের জন্য ব্যবহার করা। যদি অ্যালিসের প্রচারণা ডেভের ওয়ার্ল্ড ডমিনেশন ক্যাম্পেইন সার্ভিসেস-কে 10 ETH পাঠায়, ক্যারল কেবল জানবে যে বিল ডেভের গ্রাহকদের মধ্যে একজনকে অনুদান দিয়েছে। যদি ডেভের যথেষ্ট গ্রাহক থাকে, ক্যারল জানতে পারবে না যে বিল অ্যালিসকে অনুদান দিয়েছে যে তার সাথে প্রতিযোগিতা করে, নাকি অ্যাডাম, অ্যালবার্ট, বা অ্যাবিগেলকে দিয়েছে যাদের নিয়ে ক্যারল মাথা ঘামায় না। অ্যালিস পেমেন্টের সাথে একটি হ্যাস করা মান অন্তর্ভুক্ত করতে পারে, এবং তারপর ডেভকে প্রিইমেজ সরবরাহ করতে পারে, এটি প্রমাণ করার জন্য যে এটি তার অনুদান ছিল। বিকল্পভাবে, উপরে উল্লিখিত হিসাবে, যদি অ্যালিস ডেভকে তার _Vpriv_ দেয়, সে ইতিমধ্যেই জানে পেমেন্টটি কার কাছ থেকে এসেছে। + +এই সমাধানের প্রধান সমস্যা হল যে এটি অ্যালিসকে গোপনীয়তা সম্পর্কে যত্নবান হতে বাধ্য করে যখন সেই গোপনীয়তা বিলের উপকারে আসে। অ্যালিস তার খ্যাতি বজায় রাখতে চাইতে পারে যাতে বিলের বন্ধু ববও তাকে অনুদান দেয়। কিন্তু এটাও সম্ভব যে সে বিলকে প্রকাশ করতে আপত্তি করবে না, কারণ তাহলে সে ভয় পাবে যে ক্যারল জিতলে কী হবে। বিল হয়তো শেষ পর্যন্ত অ্যালিসকে আরও বেশি সমর্থন দেবে। + +### একাধিক স্টেলথ লেয়ার ব্যবহার করা {#multi-layer} + +বিলের গোপনীয়তা রক্ষার জন্য অ্যালিসের উপর নির্ভর না করে, বিল নিজেই এটি করতে পারে। সে কাল্পনিক ব্যক্তি, বব এবং বেলার জন্য একাধিক মেটা-অ্যাড্রেস তৈরি করতে পারে। বিল তারপর ববকে ETH পাঠায়, এবং "বব" (যে আসলে বিল) তা বেলাকে পাঠায়। "বেলা" (সেও বিল) তা অ্যালিসকে পাঠায়। + +ক্যারল এখনও ট্র্যাফিক বিশ্লেষণ করতে পারে এবং বিল-থেকে-বব-থেকে-বেলা-থেকে-অ্যালিস পাইপলাইন দেখতে পারে। যাইহোক, যদি "বব" এবং "বেলা" অন্যান্য উদ্দেশ্যেও ETH ব্যবহার করে, তাহলে এটা মনে হবে না যে বিল অ্যালিসকে কিছু ট্রান্সফার করেছে, এমনকি যদি অ্যালিস অবিলম্বে স্টেলথ অ্যাড্রেস থেকে তার পরিচিত ক্যাম্পেইন অ্যাড্রেসে উইথড্র করে। + +## একটি স্টেলথ-অ্যাড্রেস অ্যাপ্লিকেশন লেখা {#write-app} + +এই আর্টিকেলটি একটি স্টেলথ-অ্যাড্রেস অ্যাপ্লিকেশন ব্যাখ্যা করে যা [GitHub-এ উপলব্ধ](https://github.com/qbzzt/251022-stealth-addresses.git)। + +### টুলস {#tools} + +এখানে [একটি টাইপস্ক্রিপ্ট স্টেলথ অ্যাড্রেস লাইব্রেরি](https://github.com/ScopeLift/stealth-address-sdk) রয়েছে যা আমরা ব্যবহার করতে পারি। যাইহোক, ক্রিপ্টোগ্রাফিক অপারেশনগুলি CPU-ইনটেনসিভ হতে পারে। আমি সেগুলিকে [Rust](https://rust-lang.org/)-এর মতো একটি কম্পাইল করা ভাষায় ইমপ্লিমেন্ট করতে পছন্দ করি এবং ব্রাউজারে কোড চালানোর জন্য [WASM](https://webassembly.org/) ব্যবহার করি। + +আমরা [Vite](https://vite.dev/) এবং [React](https://react.dev/) ব্যবহার করতে যাচ্ছি। এগুলি ইন্ডাস্ট্রি-স্ট্যান্ডার্ড টুলস; আপনি যদি এগুলির সাথে পরিচিত না হন, তবে আপনি [এই টিউটোরিয়ালটি](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) ব্যবহার করতে পারেন। Vite ব্যবহার করতে, আমাদের নোড প্রয়োজন। + +### স্টেলথ অ্যাড্রেস বাস্তবে দেখুন {#in-action} + +1. প্রয়োজনীয় টুলস ইনস্টল করুন: [Rust](https://rust-lang.org/tools/install/) এবং [নোড](https://nodejs.org/en/download)। + +2. GitHub রিপোজিটরিটি ক্লোন করুন। + + ```sh + git clone https://github.com/qbzzt/251022-stealth-addresses.git + cd 251022-stealth-addresses + ``` + +3. পূর্বশর্তগুলি ইনস্টল করুন এবং Rust কোড কম্পাইল করুন। + + ```sh + cd src/rust-wasm + rustup target add wasm32-unknown-unknown + cargo install wasm-pack + wasm-pack build --target web + ``` + +4. ওয়েব সার্ভার শুরু করুন। + + ```sh + cd ../.. + npm install + npm run dev + ``` + +5. [অ্যাপ্লিকেশনটিতে](http://localhost:5173/) ব্রাউজ করুন। এই অ্যাপ্লিকেশন পেজটিতে দুটি ফ্রেম রয়েছে: একটি অ্যালিসের ইউজার ইন্টারফেসের জন্য এবং অন্যটি বিলের জন্য। দুটি ফ্রেম যোগাযোগ করে না; তারা শুধুমাত্র সুবিধার জন্য একই পেজে রয়েছে। + +6. অ্যালিস হিসাবে, **Generate a Stealth Meta-Address** এ ক্লিক করুন। এটি নতুন স্টেলথ অ্যাড্রেস এবং সংশ্লিষ্ট প্রাইভেট কীগুলি প্রদর্শন করবে। স্টেলথ মেটা-অ্যাড্রেসটি ক্লিপবোর্ডে কপি করুন। + +7. বিল হিসাবে, নতুন স্টেলথ মেটা-অ্যাড্রেসটি পেস্ট করুন এবং **Generate an address** এ ক্লিক করুন। এটি আপনাকে অ্যালিসের জন্য ফান্ড করার অ্যাড্রেস দেয়। + +8. অ্যাড্রেস এবং বিলের পাবলিক কী কপি করুন এবং সেগুলিকে অ্যালিসের ইউজার ইন্টারফেসের "Private key for address generated by Bill" অংশে পেস্ট করুন। একবার সেই ফিল্ডগুলি পূরণ হয়ে গেলে, আপনি সেই অ্যাড্রেসে অ্যাসেট অ্যাক্সেস করার জন্য প্রাইভেট কী দেখতে পাবেন। + +9. প্রাইভেট কী অ্যাড্রেসের সাথে সঙ্গতিপূর্ণ কিনা তা নিশ্চিত করতে আপনি [একটি অনলাইন ক্যালকুলেটর](https://iancoleman.net/ethereum-private-key-to-address/) ব্যবহার করতে পারেন। + +### প্রোগ্রামটি কীভাবে কাজ করে {#how-the-program-works} + +#### WASM কম্পোনেন্ট {#wasm} + +WASM-এ কম্পাইল হওয়া সোর্স কোড [Rust](https://rust-lang.org/) এ লেখা। আপনি এটি [`src/rust_wasm/src/lib.rs`](https://github.com/qbzzt/251022-stealth-addresses/blob/main/src/rust-wasm/src/lib.rs) এ দেখতে পারেন। এই কোডটি মূলত জাভাস্ক্রিপ্ট কোড এবং [`eth-stealth-addresses` লাইব্রেরি](https://github.com/kassandraoftroy/eth-stealth-addresses) এর মধ্যে একটি ইন্টারফেস। + +**`Cargo.toml`** + +Rust-এ [`Cargo.toml`](https://doc.rust-lang.org/cargo/reference/manifest.html) জাভাস্ক্রিপ্টে [`package.json`](https://docs.npmjs.com/cli/v9/configuring-npm/package-json) এর অনুরূপ। এতে প্যাকেজ তথ্য, ডিপেন্ডেন্সি ঘোষণা ইত্যাদি থাকে। + +```toml +[package] +name = "rust-wasm" +version = "0.1.0" +edition = "2024" + +[dependencies] +eth-stealth-addresses = "0.1.0" +hex = "0.4.3" +wasm-bindgen = "0.2.104" +getrandom = { version = "0.2", features = ["js"] } +``` + +[`getrandom`](https://docs.rs/getrandom/latest/getrandom/) প্যাকেজটিকে র‍্যান্ডম মান তৈরি করতে হবে। এটি শুধুমাত্র অ্যালগরিদমিক উপায়ে করা যায় না; এর জন্য এনট্রপির উৎস হিসাবে একটি শারীরিক প্রক্রিয়ায় অ্যাক্সেস প্রয়োজন। এই সংজ্ঞাটি নির্দিষ্ট করে যে আমরা যে ব্রাউজারে চালাচ্ছি তাকে জিজ্ঞাসা করে সেই এনট্রপি পাব। + +```toml +console_error_panic_hook = "0.1.7" +``` + +[এই লাইব্রেরিটি](https://docs.rs/console_error_panic_hook/latest/console_error_panic_hook/) আমাদের আরও অর্থপূর্ণ ত্রুটির বার্তা দেয় যখন WASM কোড প্যানিক করে এবং চলতে পারে না। + +```toml +[lib] +crate-type = ["cdylib", "rlib"] +``` + +WASM কোড তৈরি করার জন্য প্রয়োজনীয় আউটপুট টাইপ। + +**`lib.rs`** + +এটি আসল Rust কোড। + +```rust +use wasm_bindgen::prelude::*; +``` + +Rust থেকে একটি WASM প্যাকেজ তৈরি করার জন্য সংজ্ঞা। এগুলি [এখানে](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/index.html) ডকুমেন্ট করা আছে। + +```rust +use eth_stealth_addresses::{ + generate_stealth_meta_address, + generate_stealth_address, + compute_stealth_key +}; +``` + +[`eth-stealth-addresses` লাইব্রেরি](https://github.com/kassandraoftroy/eth-stealth-addresses) থেকে আমাদের প্রয়োজনীয় ফাংশন। + +```rust +use hex::{decode,encode}; +``` + +Rust সাধারণত মানগুলির জন্য বাইট [অ্যারে](https://doc.rust-lang.org/std/primitive.array.html) (`[u8; ]`) ব্যবহার করে। কিন্তু জাভাস্ক্রিপ্টে, আমরা সাধারণত হেক্সাডেসিমেল স্ট্রিং ব্যবহার করি। [`hex` লাইব্রেরি](https://docs.rs/hex/latest/hex/) আমাদের জন্য একটি রিপ্রেজেন্টেশন থেকে অন্যটিতে অনুবাদ করে। + +```rust +#[wasm_bindgen] +``` + +জাভাস্ক্রিপ্ট থেকে এই ফাংশনটি কল করতে সক্ষম হওয়ার জন্য WASM বাইন্ডিং তৈরি করুন। + +```rust +pub fn wasm_generate_stealth_meta_address() -> String { +``` + +একাধিক ফিল্ড সহ একটি অবজেক্ট ফেরত দেওয়ার সবচেয়ে সহজ উপায় হল একটি JSON স্ট্রিং ফেরত দেওয়া। + +```rust + let (address, spend_private_key, view_private_key) = + generate_stealth_meta_address(); +``` + +[`generate_stealth_meta_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_meta_address.html) তিনটি ফিল্ড প্রদান করে: + +- মেটা-অ্যাড্রেস (_Kpub_ এবং _Vpub_) +- ভিউয়িং প্রাইভেট কী (_Vpriv_) +- স্পেন্ডিং প্রাইভেট কী (_Kpriv_) + +[টাপল](https://doc.rust-lang.org/std/primitive.tuple.html) সিনট্যাক্স আমাদের সেই মানগুলিকে আবার আলাদা করতে দেয়। + +```rust + format!("{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}", + encode(address), + encode(view_private_key), + encode(spend_private_key) + ) +} +``` + +JSON-এনকোডেড স্ট্রিং তৈরি করতে [`format!`](https://doc.rust-lang.org/std/fmt/index.html) ম্যাক্রো ব্যবহার করুন। অ্যারেগুলিকে হেক্স স্ট্রিং-এ পরিবর্তন করতে [`hex::encode`](https://docs.rs/hex/latest/hex/fn.encode.html) ব্যবহার করুন। + +```rust +fn str_to_array(s: &str) -> Option<[u8; N]> { +``` + +এই ফাংশনটি একটি হেক্স স্ট্রিংকে (জাভাস্ক্রিপ্ট দ্বারা সরবরাহ করা) একটি বাইট অ্যারেতে পরিণত করে। আমরা এটি জাভাস্ক্রিপ্ট কোড দ্বারা সরবরাহ করা মানগুলি পার্স করতে ব্যবহার করি। ফাংশনটি জটিল কারণ Rust যেভাবে অ্যারে এবং ভেক্টর পরিচালনা করে। + +`` এক্সপ্রেশনটিকে [জেনেরিক](https://doc.rust-lang.org/book/ch10-01-syntax.html) বলা হয়। `N` একটি প্যারামিটার যা প্রত্যাবর্তিত অ্যারের দৈর্ঘ্য নিয়ন্ত্রণ করে। ফাংশনটি আসলে `str_to_array::` নামে পরিচিত, যেখানে `n` হল অ্যারের দৈর্ঘ্য। + +রিটার্ন ভ্যালু হল `Option<[u8; N]>`, যার মানে হল রিটার্ন করা অ্যারেটি [অপশনাল](https://doc.rust-lang.org/std/option/)। এটি Rust-এ এমন ফাংশনগুলির জন্য একটি সাধারণ প্যাটার্ন যা ব্যর্থ হতে পারে। + +উদাহরণস্বরূপ, যদি আমরা `str_to_array::10("bad060a7")` কল করি, ফাংশনটি একটি দশ-মানের অ্যারে রিটার্ন করার কথা, কিন্তু ইনপুটটি মাত্র চার বাইট। ফাংশনটি ব্যর্থ হতে হবে, এবং এটি `None` রিটার্ন করে তা করে। `str_to_array::4("bad060a7")`-এর জন্য রিটার্ন মান হবে `Some<[0xba, 0xd0, 0x60, 0xa7]>`। + +```rust + // ডিকোড Result, _> রিটার্ন করে + let vec = decode(s).ok()?; +``` + +[`hex::decode`](https://docs.rs/hex/latest/hex/fn.decode.html) ফাংশনটি একটি `Result, FromHexError>` রিটার্ন করে। [`Result`](https://doc.rust-lang.org/std/result/) টাইপে হয় একটি সফল ফলাফল (`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` নিশ্চিত করে যে সমস্ত ত্রুটি কোনো না কোনোভাবে হ্যান্ডেল করা হয়। + +```rust + if vec.len() != N { return None; } +``` + +যদি বাইট সংখ্যা ভুল হয়, তবে এটি একটি ব্যর্থতা, এবং আমরা `None` রিটার্ন করি। + +```rust + // try_into vec কনজিউম করে এবং [u8; N] তৈরি করার চেষ্টা করে + let array: [u8; N] = vec.try_into().ok()?; +``` + +Rust-এ দুটি অ্যারে টাইপ রয়েছে। [অ্যারেগুলির](https://doc.rust-lang.org/std/primitive.array.html) একটি নির্দিষ্ট আকার থাকে। [ভেক্টরগুলি](https://doc.rust-lang.org/std/vec/index.html) বাড়তে এবং সঙ্কুচিত হতে পারে। `hex::decode` একটি ভেক্টর রিটার্ন করে, কিন্তু `eth_stealth_addresses` লাইব্রেরি অ্যারে গ্রহণ করতে চায়। [`.try_into()`](https://doc.rust-lang.org/std/convert/trait.TryInto.html#required-methods) একটি মানকে অন্য একটি টাইপে রূপান্তর করে, উদাহরণস্বরূপ, একটি ভেক্টরকে একটি অ্যারেতে। + +```rust + Some(array) +} +``` + +Rust-এ ফাংশনের শেষে একটি মান রিটার্ন করার সময় [`return`](https://doc.rust-lang.org/std/keyword.return.html) কীওয়ার্ড ব্যবহার করার প্রয়োজন হয় না। + +```rust +#[wasm_bindgen] +pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option { +``` + +এই ফাংশনটি একটি পাবলিক মেটা-অ্যাড্রেস গ্রহণ করে, যার মধ্যে _Vpub_ এবং _Kpub_ উভয়ই রয়েছে। এটি স্টেলথ অ্যাড্রেস, প্রকাশ করার জন্য পাবলিক কী (_Rpub_), এবং একটি এক-বাইট স্ক্যান মান রিটার্ন করে যা কোন প্রকাশিত অ্যাড্রেসগুলি অ্যালিসের হতে পারে তা সনাক্তকরণকে দ্রুত করে। + +স্ক্যান মানটি শেয়ার্ড সিক্রেটের অংশ (_S = GRprivVpriv_) এই মানটি অ্যালিসের জন্য উপলব্ধ, এবং এটি পরীক্ষা করা _f(Kpub+G\*হ্যাস(S))_ প্রকাশিত অ্যাড্রেসের সমান কিনা তা পরীক্ষা করার চেয়ে অনেক দ্রুত। + +```rust + let (address, r_pub, scan) = + generate_stealth_address(&str_to_array::<66>(stealth_address)?); +``` + +আমরা লাইব্রেরির [`generate_stealth_address`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.generate_stealth_address.html) ব্যবহার করি। + +```rust + format!("{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}", + encode(address), + encode(r_pub), + encode(&[scan]) + ).into() +} +``` + +JSON-এনকোডেড আউটপুট স্ট্রিং প্রস্তুত করুন। + +```rust +#[wasm_bindgen] +pub fn wasm_compute_stealth_key( + address: &str, + bill_pub_key: &str, + view_private_key: &str, + spend_private_key: &str +) -> Option { + . + . + . +} +``` + +এই ফাংশনটি লাইব্রেরির [`compute_stealth_key`](https://docs.rs/eth-stealth-addresses/latest/eth_stealth_addresses/fn.compute_stealth_key.html) ব্যবহার করে অ্যাড্রেস থেকে উইথড্র করার জন্য প্রাইভেট কী (_Rpriv_) গণনা করে। এই গণনার জন্য এই মানগুলি প্রয়োজন: + +- অ্যাড্রেস (_অ্যাড্রেস=f(Ppub)_) +- বিল দ্বারা তৈরি করা পাবলিক কী (_Rpub_) +- ভিউ প্রাইভেট কী (_Vpriv_) +- স্পেন্ড প্রাইভেট কী (_Kpriv_) + +```rust +#[wasm_bindgen(start)] +``` + +[`#[wasm_bindgen(start)]`](https://wasm-bindgen.github.io/wasm-bindgen/reference/attributes/on-rust-exports/start.html) নির্দিষ্ট করে যে ফাংশনটি WASM কোড ইনিশিয়ালাইজ করা হলে এক্সিকিউট করা হয়। + +```rust +pub fn main() { + console_error_panic_hook::set_once(); +} +``` + +এই কোডটি নির্দিষ্ট করে যে প্যানিক আউটপুট জাভাস্ক্রিপ্ট কনসোলে পাঠানো হবে। এটি বাস্তবে দেখতে, অ্যাপ্লিকেশনটি ব্যবহার করুন এবং বিলকে একটি অবৈধ মেটা-অ্যাড্রেস দিন (শুধু একটি হেক্সাডেসিমেল ডিজিট পরিবর্তন করুন)। আপনি জাভাস্ক্রিপ্ট কনসোলে এই ত্রুটিটি দেখতে পাবেন: + +``` +rust_wasm.js:236 panicked at /home/ori/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/subtle-2.6.1/src/lib.rs:701:9: +assertion `left == right` failed + left: 0 + right: 1 +``` + +এরপরে একটি স্ট্যাক ট্রেস থাকে। তারপর বিলকে বৈধ মেটা-অ্যাড্রেস দিন, এবং অ্যালিসকে একটি অবৈধ অ্যাড্রেস বা একটি অবৈধ পাবলিক কী দিন। আপনি এই ত্রুটি দেখতে পাবেন: + +``` +rust_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: +keys do not generate stealth address +``` + +আবার, এরপরে একটি স্ট্যাক ট্রেস থাকে। + +#### ইউজার ইন্টারফেস {#ui} + +ইউজার ইন্টারফেসটি [React](https://react.dev/) ব্যবহার করে লেখা এবং [Vite](https://vite.dev/) দ্বারা পরিবেশন করা হয়। আপনি [এই টিউটোরিয়ালটি](/developers/tutorials/creating-a-wagmi-ui-for-your-contract/) ব্যবহার করে সেগুলি সম্পর্কে জানতে পারেন। এখানে [WAGMI](https://wagmi.sh/) এর কোনো প্রয়োজন নেই কারণ আমরা সরাসরি ব্লকচেইন বা ওয়ালেটের সাথে ইন্টারঅ্যাক্ট করি না। + +ইউজার ইন্টারফেসের একমাত্র অ-স্বাভাবিক অংশ হল WASM কানেক্টিভিটি। এটি কীভাবে কাজ করে তা এখানে দেওয়া হলো। + +**`vite.config.js`** + +এই ফাইলটিতে [Vite কনফিগারেশন](https://vite.dev/config/) রয়েছে। + +```js +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' +import wasm from "vite-plugin-wasm"; + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), wasm()], +}) +``` + +আমাদের দুটি Vite প্লাগইন প্রয়োজন: [react](https://www.npmjs.com/package/@vitejs/plugin-react) এবং [wasm](https://github.com/Menci/vite-plugin-wasm#readme)। + +**`App.jsx`** + +এই ফাইলটি অ্যাপ্লিকেশনের প্রধান কম্পোনেন্ট। এটি একটি কন্টেইনার যা দুটি কম্পোনেন্ট অন্তর্ভুক্ত করে: `Alice` এবং `Bill`, যা ঐ ব্যবহারকারীদের জন্য ইউজার ইন্টারফেস। WASM-এর জন্য প্রাসঙ্গিক অংশটি হলো ইনিশিয়ালাইজেশন কোড। + +```jsx +import init from './rust-wasm/pkg/rust_wasm.js' +``` + +যখন আমরা [`wasm-pack`](https://rustwasm.github.io/docs/wasm-pack/) ব্যবহার করি, তখন এটি দুটি ফাইল তৈরি করে যা আমরা এখানে ব্যবহার করি: আসল কোড সহ একটি wasm ফাইল (এখানে, `src/rust-wasm/pkg/rust_wasm_bg.wasm`) এবং এটি ব্যবহার করার জন্য সংজ্ঞা সহ একটি জাভাস্ক্রিপ্ট ফাইল (এখানে, `src/rust-wasm/pkg/rust_wasm.js`)। সেই জাভাস্ক্রিপ্ট ফাইলের ডিফল্ট এক্সপোর্ট হল কোড যা WASM শুরু করার জন্য চালাতে হবে। + +```jsx +function App() { + . + . + . + useEffect(() => { + const loadWasm = async () => { + try { + await init(); + setWasmReady(true) + } catch (err) { + console.error('wasm লোড করতে ত্রুটি:', err) + alert("Wasm error: " + err) + } + } + + loadWasm() + }, [] + ) +``` + +[`useEffect` হুক](https://react.dev/reference/react/useEffect) আপনাকে একটি ফাংশন নির্দিষ্ট করতে দেয় যা স্টেট ভ্যারিয়েবল পরিবর্তন হলে এক্সিকিউট হয়। এখানে, স্টেট ভ্যারিয়েবলের তালিকা খালি (`[]`), তাই এই ফাংশনটি পেজ লোড হওয়ার সময় শুধুমাত্র একবার এক্সিকিউট হয়। + +ইফেক্ট ফাংশনটিকে অবিলম্বে রিটার্ন করতে হবে। অ্যাসিঙ্ক্রোনাস কোড ব্যবহার করার জন্য, যেমন WASM `init` (যা `.wasm` ফাইল লোড করতে হয় এবং তাই সময় নেয়), আমরা একটি অভ্যন্তরীণ [`async`](https://en.wikipedia.org/wiki/Async/await) ফাংশন সংজ্ঞায়িত করি এবং `await` ছাড়াই এটি চালাই। + +**`Bill.jsx`** + +এটি বিলের জন্য ইউজার ইন্টারফেস। এর একটিমাত্র অ্যাকশন আছে, যা হল অ্যালিসের দেওয়া স্টেলথ মেটা-অ্যাড্রেসের উপর ভিত্তি করে একটি অ্যাড্রেস তৈরি করা। + +```jsx +import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js' +``` + +`wasm-pack` দ্বারা তৈরি জাভাস্ক্রিপ্ট কোডটি ডিফল্ট এক্সপোর্ট ছাড়াও, WASM কোডের প্রতিটি ফাংশনের জন্য একটি ফাংশন এক্সপোর্ট করে। + +```jsx +