استخدام عناوين التخفي
أنت بيل. لأسباب لن نخوض فيها، تريد التبرع لحملة "أليس من أجل ملكة العالم" وأن تعلم أليس أنك تبرعت حتى تكافئك إذا فازت. لسوء الحظ، فوزها غير مضمون. هناك حملة منافسة، "كارول من أجل إمبراطورة النظام الشمسي". إذا فازت كارول، واكتشفت أنك تبرعت لأليس، فستقع في ورطة. لذلك لا يمكنك ببساطة تحويل 200 ETH من حسابك إلى حساب أليس.
لدى ERC-5564 (opens in a new tab) الحل. يشرح ERC هذا كيفية استخدام عناوين التخفي (opens in a new tab) للتحويل المجهول.
تحذير: علم التشفير وراء عناوين التخفي، على حد علمنا، سليم. ومع ذلك، هناك هجمات محتملة عبر القنوات الجانبية. أدناه، سترى ما يمكنك فعله لتقليل هذا الخطر.
كيفية عمل عناوين التخفي
سيحاول هذا المقال شرح عناوين التخفي بطريقتين. الأولى هي كيفية استخدامها. هذا الجزء كافٍ لفهم بقية المقال. ثم، هناك شرح للرياضيات التي تقف وراءها. إذا كنت مهتمًا بعلم التشفير، فاقرأ هذا الجزء أيضًا.
النسخة المبسطة (كيفية استخدام عناوين التخفي)
تنشئ أليس مفتاحين خاصين وتنشر المفاتيح العامة المقابلة (والتي يمكن دمجها في عنوان meta-address واحد مزدوج الطول). ينشئ بيل أيضًا مفتاحًا خاصًا وينشر المفتاح العام المقابل.
باستخدام المفتاح العام لأحد الطرفين والمفتاح الخاص للطرف الآخر، يمكنك اشتقاق سر مشترك لا يعرفه سوى أليس وبيل (لا يمكن اشتقاقه من المفاتيح العامة وحدها). باستخدام هذا السر المشترك، يحصل بيل على عنوان التخفي ويمكنه إرسال الأصول إليه.
تحصل أليس أيضًا على العنوان من السر المشترك، ولكن لأنها تعرف المفاتيح الخاصة للمفاتيح العامة التي نشرتها، يمكنها أيضًا الحصول على المفتاح الخاص الذي يسمح لها بالسحب من هذا العنوان.
الرياضيات (لماذا تعمل عناوين التخفي بهذه الطريقة)
تستخدم عناوين التخفي القياسية تشفير المنحنى الإهليلجي (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).
لدينا مفتاح عرض منفصل للسماح لأليس بالتعاقد من الباطن مع خدمات حملة Dave للسيطرة على العالم. أليس على استعداد لإبلاغ Dave بالعناوين العامة وإبلاغها عند توفر المزيد من الأموال، لكنها لا تريده أن ينفق أموال حملتها.
لأن العرض والإنفاق يستخدمان مفاتيح منفصلة، يمكن لأليس أن تعطي Dave Vpriv. ثم يمكن لـ Dave حساب S = RpubVpriv = GRprivVpriv وبهذه الطريقة يحصل على المفاتيح العامة (Ppub = Kpub+G*hash(S)). ولكن بدون Kpriv لا يستطيع Dave الحصول على المفتاح الخاص.
للتلخيص، هذه هي القيم التي يعرفها المشاركون المختلفون.
| أليس | منشور | بيل | ديف | |
|---|---|---|---|---|
| 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) | |
| Address=f(Ppub) | ـ | Address=f(Ppub) | Address=f(Ppub) | Address=f(Ppub) |
| Ppriv = Kpriv+hash(S) | ـ | ـ | ـ |
عندما تسوء عناوين التخفي
لا توجد أسرار على البلوكتشين. بينما يمكن أن توفر لك عناوين التخفي الخصوصية، فإن هذه الخصوصية عرضة لتحليل حركة المرور. لاختيار مثال تافه، تخيل أن بيل يمول عنوانًا ويرسل على الفور معاملة لنشر قيمة Rpub. بدون Vpriv الخاص بأليس، لا يمكننا التأكد من أن هذا عنوان تخفي، ولكن هذا هو الرهان الأرجح. بعد ذلك، نرى معاملة أخرى تحول كل ETH من هذا العنوان إلى عنوان صندوق حملة أليس. قد لا نتمكن من إثبات ذلك، ولكن من المحتمل أن بيل قد تبرع للتو لحملة أليس. بالتأكيد ستفكر كارول كذلك.
من السهل على بيل فصل نشر Rpub عن تمويل عنوان التخفي (القيام بهما في أوقات مختلفة، ومن عناوين مختلفة). ومع ذلك، هذا غير كاف. النمط الذي تبحث عنه كارول هو أن بيل يمول عنوانًا، ثم يسحب صندوق حملة أليس منه.
أحد الحلول هو ألا تسحب حملة أليس الأموال مباشرة، بل تستخدمها للدفع لطرف ثالث. إذا أرسلت حملة أليس 10 ETH إلى خدمات حملة Dave للسيطرة على العالم، فإن كارول تعرف فقط أن بيل تبرع لأحد عملاء Dave. إذا كان لدى Dave عدد كافٍ من العملاء، فلن تتمكن كارول من معرفة ما إذا كان بيل قد تبرع لأليس التي تتنافس معها، أو لآدم أو ألبرت أو أبيجيل الذين لا تهتم بهم كارول. يمكن لأليس تضمين قيمة مجزأة مع الدفعة، ثم تزويد Dave بالصورة الأولية، لإثبات أنها كانت تبرعها. بدلاً من ذلك، كما هو مذكور أعلاه، إذا أعطت أليس لـ Dave مفتاحها Vpriv، فهو يعرف بالفعل من أين جاءت الدفعة.
المشكلة الرئيسية في هذا الحل هي أنه يتطلب من أليس الاهتمام بالسرية عندما تفيد هذه السرية بيل. قد ترغب أليس في الحفاظ على سمعتها حتى يتبرع لها صديق بيل، بوب، أيضًا. ولكن من الممكن أيضًا ألا تمانع في فضح بيل، لأنه حينها سيخاف مما سيحدث إذا فازت كارول. قد ينتهي الأمر ببيل بتقديم المزيد من الدعم لأليس.
استخدام طبقات تخفي متعددة
بدلاً من الاعتماد على أليس للحفاظ على خصوصية بيل، يمكن لبيل أن يفعل ذلك بنفسه. يمكنه إنشاء عناوين meta-addresses متعددة لأشخاص وهميين، بوب وبيلا. ثم يرسل بيل ETH إلى بوب، و"بوب" (وهو في الواقع بيل) يرسله إلى بيلا. "بيلا" (وهي أيضًا بيل) ترسلها إلى أليس.
لا يزال بإمكان كارول إجراء تحليل لحركة المرور ورؤية خط أنابيب بيل-إلى-بوب-إلى-بيلا-إلى-أليس. ومع ذلك، إذا استخدم "بوب" و"بيلا" أيضًا ETH لأغراض أخرى، فلن يظهر أن بيل قد حول أي شيء إلى أليس، حتى لو سحبت أليس على الفور من عنوان التخفي إلى عنوان حملتها المعروف.
كتابة تطبيق عنوان تخفي
يشرح هذا المقال تطبيق عنوان تخفي متوفر على غيت هاب (opens in a new tab).
أدوات
هناك مكتبة عناوين تخفي typescript (opens in a new tab) يمكننا استخدامها. ومع ذلك، يمكن أن تكون العمليات المشفرة كثيفة الاستخدام لوحدة المعالجة المركزية. أفضل تنفيذها بلغة مجمعة، مثل راست (opens in a new tab)، واستخدام WASM (opens in a new tab) لتشغيل النص البرمجي في المتصفح.
سنستخدم فيت (opens in a new tab) و رياكت (opens in a new tab). هذه أدوات قياسية في الصناعة؛ إذا لم تكن على دراية بها، يمكنك استخدام هذا البرنامج التعليمي. لاستخدام فيت، نحتاج إلى Node.
شاهد عناوين التخفي أثناء العمل
-
قم بتثبيت الأدوات اللازمة: راست (opens in a new tab) و Node (opens in a new tab).
-
استنسخ مستودع غيت هاب.
1git clone https://github.com/qbzzt/251022-stealth-addresses.git2cd 251022-stealth-addresses -
قم بتثبيت المتطلبات الأساسية وتجميع كود راست.
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). تحتوي صفحة التطبيق هذه على إطارين: أحدهما لواجهة مستخدم أليس والآخر لواجهة مستخدم بيل. لا يتواصل الإطاران؛ إنهما على نفس الصفحة فقط للراحة.
-
بصفتك أليس، انقر فوق إنشاء عنوان Meta-Address للتخفي. سيعرض هذا عنوان التخفي الجديد والمفاتيح الخاصة المقابلة. انسخ عنوان meta-address التخفي إلى الحافظة.
-
بصفتك بيل، الصق عنوان meta-address التخفي الجديد وانقر فوق إنشاء عنوان. يمنحك هذا العنوان لتمويل أليس.
-
انسخ العنوان والمفتاح العام لبيل والصقهما في منطقة "المفتاح الخاص للعنوان الذي أنشأه بيل" في واجهة مستخدم أليس. بمجرد ملء هذه الحقول، سترى المفتاح الخاص للوصول إلى الأصول الموجودة في ذلك العنوان.
-
يمكنك استخدام آلة حاسبة عبر الإنترنت (opens in a new tab) للتأكد من أن المفتاح الخاص يتوافق مع العنوان.
كيفية عمل البرنامج
مكون WASM
كود المصدر الذي يتم تجميعه في WASM مكتوب بلغة راست (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
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
هذا هو كود راست الفعلي.
1use wasm_bindgen::prelude::*;التعريفات لإنشاء حزمة 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};تستخدم راست عادةً مصفوفات (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}استخدم ماكرو format! (opens in a new tab) لإنشاء السلسلة المشفرة بـ JSON. استخدم hex::encode (opens in a new tab) لتغيير المصفوفات إلى سلاسل سداسية عشرية.
1fn str_to_array<const N: usize>(s: &str) -> Option<[u8; N]> {تحول هذه الدالة سلسلة سداسية عشرية (مقدمة من جافا سكريبت) إلى مصفوفة بايت. نستخدمها لتحليل القيم المقدمة من كود جافا سكريبت. هذه الدالة معقدة بسبب كيفية تعامل راست مع المصفوفات والمتجهات.
يُطلق على التعبير <const N: usize> اسم عام (opens in a new tab). N هي معلمة تتحكم في طول المصفوفة المرتجعة. الدالة تسمى في الواقع str_to_array::<n>، حيث n هو طول المصفوفة.
القيمة المرتجعة هي Option<[u8; N]>، مما يعني أن المصفوفة المرتجعة اختيارية (opens in a new tab). هذا نمط نموذجي في راست للوظائف التي قد تفشل.
على سبيل المثال، إذا استدعينا 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 إذا لم تنجح. أخيرًا، يقوم عامل علامة الاستفهام (opens in a new tab) بإيقاف الوظائف الحالية وإرجاع None إذا كان Option فارغًا. خلاف ذلك، فإنه يفك القيمة ويعيدها (في هذه الحالة، لتعيين قيمة لـ 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()?;لدى راست نوعان من المصفوفات. المصفوفات (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}لا تتطلب منك راست استخدام الكلمة المفتاحية return (opens in a new tab) عند إرجاع قيمة في نهاية دالة.
1#[wasm_bindgen]2pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option<String> {تتلقى هذه الدالة عنوان meta-address عامًا، والذي يتضمن كلاً من 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}يحدد هذا الكود إرسال مخرجات الذعر إلى وحدة تحكم جافا سكريبت. لرؤيته أثناء العمل، استخدم التطبيق وأعط بيل عنوانًا غير صالح لـ meta-address (فقط قم بتغيير رقم سداسي عشري واحد). سترى هذا الخطأ في وحدة تحكم جافا سكريبت:
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يتبعها تتبع المكدس. ثم أعط بيل عنوان meta-address صالحًا، وأعط أليس إما عنوانًا غير صالح أو مفتاحًا عامًا غير صالح. سترى هذا الخطأ:
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مرة أخرى، يتبعها تتبع المكدس.
واجهة المستخدم
واجهة المستخدم مكتوبة باستخدام رياكت (opens in a new tab) ويتم تقديمها بواسطة فيت (opens in a new tab). يمكنك التعرف عليها باستخدام هذا البرنامج التعليمي. ليست هناك حاجة لـ WAGMI (opens in a new tab) هنا لأننا لا نتفاعل مباشرة مع بلوكتشين أو محفظة.
الجزء الوحيد غير الواضح في واجهة المستخدم هو اتصال WASM. إليك كيفية عمله.
vite.config.js
يحتوي هذا الملف على تكوين فيت (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})نحتاج إلى مكونين إضافيين لـ فيت: 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) تحديد دالة يتم تنفيذها عند تغيير متغيرات الحالة. هنا، قائمة متغيرات الحالة فارغة ([])، لذلك يتم تنفيذ هذه الدالة مرة واحدة فقط عند تحميل الصفحة.
يجب أن تعود دالة التأثير على الفور. لاستخدام كود غير متزامن، مثل init الخاص بـ WASM (الذي يجب عليه تحميل ملف .wasm وبالتالي يستغرق وقتًا) ، نحدد دالة async (opens in a new tab) داخلية ونقوم بتشغيلها بدون await.
Bill.jsx
هذه هي واجهة المستخدم لبيل. لديها إجراء واحد، وهو إنشاء عنوان بناءً على عنوان meta-address التخفي الذي قدمته أليس.
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 مشابه، باستثناء أن أليس لديها إجراءان:
- إنشاء عنوان meta-address
- الحصول على المفتاح الخاص لعنوان نشره بيل
الخلاصة
عناوين التخفي ليست حلاً سحريًا؛ يجب استخدامها بشكل صحيح. ولكن عند استخدامها بشكل صحيح، يمكنها تمكين الخصوصية على بلوكتشين عام.
انظر هنا لمزيد من أعمالي (opens in a new tab).
آخر تحديث للصفحة: 14 نوفمبر 2025