Verwendung von Stealth-Adressen
Du bist Bill. Aus Gründen, auf die wir hier nicht näher eingehen, möchtest du für die Kampagne „Alice for Queen of the World“ spenden und Alice wissen lassen, dass du gespendet hast, damit sie dich belohnt, falls sie gewinnt. Leider ist ihr Sieg nicht garantiert. Es gibt eine konkurrierende Kampagne: „Carol for Empress of the Solar System“. Wenn Carol gewinnt und herausfindet, dass du an Alice gespendet hast, steckst du in Schwierigkeiten. Du kannst also nicht einfach 200 ETH von deinem Konto auf das von Alice transferieren.
ERC-5564 (opens in a new tab) bietet die Lösung. Dieser ERC erklärt, wie man Stealth-Adressen (opens in a new tab) für einen anonymen Transfer verwendet.
Warnung: Die Kryptographie hinter Stealth-Adressen ist, soweit wir wissen, solide. Es gibt jedoch potenzielle Seitenkanalangriffe. Unten wirst du sehen, was du tun kannst, um dieses Risiko zu verringern.
Wie Stealth-Adressen funktionieren
Dieser Artikel wird versuchen, Stealth-Adressen auf zwei Arten zu erklären. Die erste ist, wie man sie verwendet. Dieser Teil reicht aus, um den Rest des Artikels zu verstehen. Danach folgt eine Erklärung der dahinterstehenden Mathematik. Wenn du dich für Kryptographie interessierst, lies auch diesen Teil.
Die einfache Version (wie man Stealth-Adressen verwendet)
Alice erstellt zwei private Schlüssel und veröffentlicht die entsprechenden öffentlichen Schlüssel (die zu einer einzigen Meta-Adresse doppelter Länge kombiniert werden können). Bill erstellt ebenfalls einen privaten Schlüssel und veröffentlicht den entsprechenden öffentlichen Schlüssel.
Unter Verwendung des öffentlichen Schlüssels der einen Partei und des privaten Schlüssels der anderen kann man ein gemeinsames Geheimnis ableiten, das nur Alice und Bill bekannt ist (es kann nicht allein aus den öffentlichen Schlüsseln abgeleitet werden). Mit diesem gemeinsamen Geheimnis erhält Bill die Stealth-Adresse und kann Vermögenswerte dorthin senden.
Alice erhält die Adresse ebenfalls aus dem gemeinsamen Geheimnis, aber da sie die privaten Schlüssel zu den von ihr veröffentlichten öffentlichen Schlüsseln kennt, kann sie auch den privaten Schlüssel erhalten, der es ihr ermöglicht, von dieser Adresse abzuheben.
Die Mathematik (warum Stealth-Adressen so funktionieren)
Standard-Stealth-Adressen verwenden Elliptic Curve Cryptography (ECC) (opens in a new tab), um eine bessere Leistung mit weniger Schlüsselbits zu erzielen und gleichzeitig das gleiche Sicherheitsniveau beizubehalten. Aber größtenteils können wir das ignorieren und so tun, als würden wir normale Arithmetik verwenden.
Es gibt eine Zahl, die jeder kennt: G. Man kann mit G multiplizieren. Aber aufgrund der Natur von ECC ist es praktisch unmöglich, durch G zu dividieren. Die Art und Weise, wie Public-Key-Kryptographie in Ethereum im Allgemeinen funktioniert, besteht darin, dass man einen privaten Schlüssel, Ppriv, verwenden kann, um Transaktionen zu signieren, die dann durch einen öffentlichen Schlüssel, Ppub = GPpriv, verifiziert werden.
Alice erstellt zwei private Schlüssel, Kpriv und Vpriv. Kpriv wird verwendet, um Geld von der Stealth-Adresse auszugeben, und Vpriv, um die Adressen einzusehen, die Alice gehören. Alice veröffentlicht dann die öffentlichen Schlüssel: Kpub = GKpriv und Vpub = GVpriv
Bill erstellt einen dritten privaten Schlüssel, Rpriv, und veröffentlicht Rpub = GRpriv in einer zentralen Registratur (Bill hätte ihn auch an Alice senden können, aber wir gehen davon aus, dass Carol mithört).
Bill berechnet RprivVpub = GRprivVpriv, wovon er ausgeht, dass Alice es ebenfalls kennt (wird unten erklärt). Dieser Wert wird S genannt, das gemeinsame Geheimnis. Dies gibt Bill einen öffentlichen Schlüssel, Ppub = Kpub+G*hash(S). Aus diesem öffentlichen Schlüssel kann er eine Adresse berechnen und beliebige Ressourcen dorthin senden. Wenn Alice in Zukunft gewinnt, kann Bill ihr Rpriv mitteilen, um zu beweisen, dass die Ressourcen von ihm stammen.
Alice berechnet RpubVpriv = GRprivVpriv. Dies gibt ihr dasselbe gemeinsame Geheimnis, S. Da sie den privaten Schlüssel, Kpriv, kennt, kann sie Ppriv = Kpriv+hash(S) berechnen. Dieser Schlüssel ermöglicht ihr den Zugriff auf Vermögenswerte in der Adresse, die aus Ppub = GPpriv = GKpriv+G*hash(S) = Kpub+G*hash(S) resultiert.
Wir haben einen separaten Ansichtsschlüssel (Viewing Key), um es Alice zu ermöglichen, Dave's World Domination Campaign Services als Subunternehmer zu beauftragen. Alice ist bereit, Dave die öffentlichen Adressen wissen zu lassen und sie zu informieren, wenn mehr Geld verfügbar ist, aber sie möchte nicht, dass er ihr Kampagnengeld ausgibt.
Da für das Einsehen und Ausgeben separate Schlüssel verwendet werden, kann Alice Dave Vpriv geben. Dann kann Dave S = RpubVpriv = GRprivVpriv berechnen und auf diese Weise die öffentlichen Schlüssel (Ppub = Kpub+G*hash(S)) erhalten. Aber ohne Kpriv kann Dave den privaten Schlüssel nicht erhalten.
Zusammenfassend sind dies die Werte, die den verschiedenen Teilnehmern bekannt sind.
| Alice | Veröffentlicht | Bill | 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) |
| Adresse=f(Ppub) | - | Adresse=f(Ppub) | Adresse=f(Ppub) |
| Ppriv = Kpriv+hash(S) | - | - | - |
Wenn Stealth-Adressen schiefgehen
Es gibt keine Geheimnisse auf der Blockchain. Während Stealth-Adressen dir Privatsphäre bieten können, ist diese Privatsphäre anfällig für Verkehrsanalysen. Um ein triviales Beispiel zu wählen: Stell dir vor, Bill finanziert eine Adresse und sendet sofort eine Transaktion, um einen Rpub-Wert zu veröffentlichen. Ohne Alices Vpriv können wir nicht sicher sein, dass dies eine Stealth-Adresse ist, aber es ist sehr wahrscheinlich. Dann sehen wir eine weitere Transaktion, die alle ETH von dieser Adresse auf die Adresse von Alices Kampagnenfonds transferiert. Wir können es vielleicht nicht beweisen, aber es ist wahrscheinlich, dass Bill gerade für Alices Kampagne gespendet hat. Carol würde das sicherlich denken.
Es ist für Bill einfach, die Veröffentlichung von Rpub von der Finanzierung der Stealth-Adresse zu trennen (indem er sie zu unterschiedlichen Zeiten von unterschiedlichen Adressen aus durchführt). Das ist jedoch unzureichend. Das Muster, nach dem Carol sucht, ist, dass Bill eine Adresse finanziert und dann Alices Kampagnenfonds davon abhebt.
Eine Lösung besteht darin, dass Alices Kampagne das Geld nicht direkt abhebt, sondern es verwendet, um einen Dritten zu bezahlen. Wenn Alices Kampagne 10 ETH an Dave's World Domination Campaign Services sendet, weiß Carol nur, dass Bill an einen von Daves Kunden gespendet hat. Wenn Dave genug Kunden hat, könnte Carol nicht wissen, ob Bill an Alice gespendet hat, die mit ihr konkurriert, oder an Adam, Albert oder Abigail, die Carol egal sind. Alice kann der Zahlung einen gehashten Wert beifügen und Dave dann das Urbild (Preimage) zur Verfügung stellen, um zu beweisen, dass es ihre Spende war. Alternativ, wie oben angemerkt, weiß Dave bereits, von wem die Zahlung kam, wenn Alice ihm ihr Vpriv gibt.
Das Hauptproblem bei dieser Lösung ist, dass sie voraussetzt, dass Alice sich um Geheimhaltung kümmert, wenn diese Geheimhaltung Bill zugutekommt. Alice möchte vielleicht ihren Ruf wahren, damit Bills Freund Bob ebenfalls an sie spendet. Aber es ist auch möglich, dass es ihr nichts ausmacht, Bill bloßzustellen, weil er dann Angst davor hat, was passiert, wenn Carol gewinnt. Bill könnte am Ende Alice noch mehr Unterstützung zukommen lassen.
Verwendung mehrerer Stealth-Ebenen
Anstatt sich darauf zu verlassen, dass Alice Bills Privatsphäre wahrt, kann Bill dies selbst tun. Er kann mehrere Meta-Adressen für fiktive Personen, Bob und Bella, generieren. Bill sendet dann ETH an Bob, und „Bob“ (der eigentlich Bill ist) sendet es an Bella. „Bella“ (ebenfalls Bill) sendet es an Alice.
Carol kann immer noch eine Verkehrsanalyse durchführen und die Pipeline von Bill zu Bob zu Bella zu Alice sehen. Wenn „Bob“ und „Bella“ jedoch ETH auch für andere Zwecke verwenden, wird es nicht so aussehen, als hätte Bill etwas an Alice transferiert, selbst wenn Alice sofort von der Stealth-Adresse auf ihre bekannte Kampagnenadresse abhebt.
Schreiben einer Stealth-Adressen-Anwendung
Dieser Artikel erklärt eine Stealth-Adressen-Anwendung, die auf GitHub verfügbar (opens in a new tab) ist.
Werkzeuge
Es gibt eine TypeScript-Stealth-Adressen-Bibliothek (opens in a new tab), die wir verwenden könnten. Kryptographische Operationen können jedoch CPU-intensiv sein. Ich ziehe es vor, sie in einer kompilierten Sprache wie Rust (opens in a new tab) zu implementieren und WASM (opens in a new tab) zu verwenden, um den Code im Browser auszuführen.
Wir werden Vite (opens in a new tab) und React (opens in a new tab) verwenden. Dies sind branchenübliche Werkzeuge; wenn du nicht mit ihnen vertraut bist, kannst du dieses Tutorial verwenden. Um Vite zu verwenden, benötigen wir Node.
Stealth-Adressen in Aktion sehen
-
Installiere die notwendigen Werkzeuge: Rust (opens in a new tab) und Node (opens in a new tab).
-
Klone das GitHub-Repository.
git clone https://github.com/qbzzt/251022-stealth-addresses.git cd 251022-stealth-addresses -
Installiere die Voraussetzungen und kompiliere den Rust-Code.
cd src/rust-wasm rustup target add wasm32-unknown-unknown cargo install wasm-pack wasm-pack build --target web -
Starte den Webserver.
cd ../.. npm install npm run dev -
Navigiere zu der Anwendung (opens in a new tab). Diese Anwendungsseite hat zwei Frames: einen für Alices Benutzeroberfläche und den anderen für Bills. Die beiden Frames kommunizieren nicht miteinander; sie befinden sich nur der Einfachheit halber auf derselben Seite.
-
Klicke als Alice auf Generate a Stealth Meta-Address. Dadurch werden die neue Stealth-Adresse und die entsprechenden privaten Schlüssel angezeigt. Kopiere die Stealth-Meta-Adresse in die Zwischenablage.
-
Füge als Bill die neue Stealth-Meta-Adresse ein und klicke auf Generate an address. Dies gibt dir die Adresse, die du für Alice finanzieren kannst.
-
Kopiere die Adresse und Bills öffentlichen Schlüssel und füge sie in den Bereich „Private key for address generated by Bill“ von Alices Benutzeroberfläche ein. Sobald diese Felder ausgefüllt sind, siehst du den privaten Schlüssel, um auf die Vermögenswerte an dieser Adresse zuzugreifen.
-
Du kannst einen Online-Rechner (opens in a new tab) verwenden, um sicherzustellen, dass der private Schlüssel der Adresse entspricht.
Wie das Programm funktioniert
Die WASM-Komponente
Der Quellcode, der zu WASM kompiliert wird, ist in Rust (opens in a new tab) geschrieben. Du kannst ihn in src/rust_wasm/src/lib.rs (opens in a new tab) sehen. Dieser Code ist in erster Linie eine Schnittstelle zwischen dem JavaScript-Code und der eth-stealth-addresses-Bibliothek (opens in a new tab).
Cargo.toml
Cargo.toml (opens in a new tab) in Rust ist analog zu package.json (opens in a new tab) in JavaScript. Es enthält Paketinformationen, Abhängigkeitsdeklarationen usw.
[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"] }
Das getrandom (opens in a new tab)-Paket muss Zufallswerte generieren. Das kann nicht durch rein algorithmische Mittel geschehen; es erfordert den Zugriff auf einen physikalischen Prozess als Quelle der Entropie. Diese Definition legt fest, dass wir diese Entropie erhalten, indem wir den Browser abfragen, in dem wir ausgeführt werden.
console_error_panic_hook = "0.1.7"
Diese Bibliothek (opens in a new tab) liefert uns aussagekräftigere Fehlermeldungen, wenn der WASM-Code in Panik gerät (panics) und nicht fortgesetzt werden kann.
[lib]
crate-type = ["cdylib", "rlib"]
Der Ausgabetyp, der erforderlich ist, um WASM-Code zu erzeugen.
lib.rs
Dies ist der eigentliche Rust-Code.
use wasm_bindgen::prelude::*;
Die Definitionen, um ein WASM-Paket aus Rust zu erstellen. Sie sind hier (opens in a new tab) dokumentiert.
use eth_stealth_addresses::{
generate_stealth_meta_address,
generate_stealth_address,
compute_stealth_key
};
Die Funktionen, die wir aus der eth-stealth-addresses-Bibliothek (opens in a new tab) benötigen.
use hex::{decode,encode};
Rust verwendet typischerweise Byte-Arrays (opens in a new tab) ([u8; <size>]) für Werte. Aber in JavaScript verwenden wir typischerweise hexadezimale Strings. Die hex-Bibliothek (opens in a new tab) übersetzt für uns von einer Darstellung in die andere.
#[wasm_bindgen]
Generiere WASM-Bindings, um diese Funktion aus JavaScript aufrufen zu können.
pub fn wasm_generate_stealth_meta_address() -> String {
Der einfachste Weg, ein Objekt mit mehreren Feldern zurückzugeben, ist die Rückgabe eines JSON-Strings.
let (address, spend_private_key, view_private_key) =
generate_stealth_meta_address();
Die generate_stealth_meta_address (opens in a new tab) gibt drei Felder zurück:
- Die Meta-Adresse (Kpub und Vpub)
- Den privaten Ansichtsschlüssel (Vpriv)
- Den privaten Ausgabeschlüssel (Kpriv)
Die Tupel (opens in a new tab)-Syntax lässt uns diese Werte wieder trennen.
format!("{{\"address\":\"{}\",\"view_private_key\":\"{}\",\"spend_private_key\":\"{}\"}}",
encode(address),
encode(view_private_key),
encode(spend_private_key)
)
}
Verwende das format! (opens in a new tab)-Makro, um den JSON-kodierten String zu generieren. Verwende hex::encode (opens in a new tab), um die Arrays in Hex-Strings umzuwandeln.
fn str_to_array<const N: usize>(s: &str) -> Option<[u8; N]> {
Diese Funktion wandelt einen Hex-String (bereitgestellt von JavaScript) in ein Byte-Array um. Wir verwenden sie, um Werte zu parsen, die vom JavaScript-Code bereitgestellt werden. Diese Funktion ist kompliziert, weil Rust Arrays und Vektoren auf eine bestimmte Weise handhabt.
Der Ausdruck <const N: usize> wird als Generikum (Generic) (opens in a new tab) bezeichnet. N ist ein Parameter, der die Länge des zurückgegebenen Arrays steuert. Die Funktion wird eigentlich str_to_array::<n> genannt, wobei n die Array-Länge ist.
Der Rückgabewert ist Option<[u8; N]>, was bedeutet, dass das zurückgegebene Array optional (opens in a new tab) ist. Dies ist ein typisches Muster in Rust für Funktionen, die fehlschlagen können.
Wenn wir zum Beispiel str_to_array::10("bad060a7") aufrufen, soll die Funktion ein Array mit zehn Werten zurückgeben, aber die Eingabe ist nur vier Bytes lang. Die Funktion muss fehlschlagen, und das tut sie, indem sie None zurückgibt. Der Rückgabewert für str_to_array::4("bad060a7") wäre Some<[0xba, 0xd0, 0x60, 0xa7]>.
// decode gibt Result<Vec<u8>, _> zurück
let vec = decode(s).ok()?;
Die Funktion hex::decode (opens in a new tab) gibt ein Result<Vec<u8>, FromHexError> zurück. Der Typ Result (opens in a new tab) kann entweder ein erfolgreiches Ergebnis (Ok(value)) oder einen Fehler (Err(error)) enthalten.
Die Methode .ok() wandelt das Result in ein Option um, dessen Wert entweder der Ok()-Wert ist, wenn es erfolgreich war, oder None, wenn nicht. Schließlich bricht der Fragezeichen-Operator (opens in a new tab) die aktuelle Funktion ab und gibt ein None zurück, wenn das Option leer ist. Andernfalls entpackt (unwraps) er den Wert und gibt ihn zurück (in diesem Fall, um vec einen Wert zuzuweisen).
Dies sieht nach einer seltsam komplizierten Methode zur Fehlerbehandlung aus, aber Result und Option stellen sicher, dass alle Fehler auf die eine oder andere Weise behandelt werden.
if vec.len() != N { return None; }
Wenn die Anzahl der Bytes falsch ist, ist das ein Fehler, und wir geben None zurück.
// try_into verbraucht vec und versucht, [u8; N] zu erstellen
let array: [u8; N] = vec.try_into().ok()?;
Rust hat zwei Array-Typen. Arrays (opens in a new tab) haben eine feste Größe. Vektoren (opens in a new tab) können wachsen und schrumpfen. hex::decode gibt einen Vektor zurück, aber die eth_stealth_addresses-Bibliothek möchte Arrays empfangen. .try_into() (opens in a new tab) konvertiert einen Wert in einen anderen Typ, zum Beispiel einen Vektor in ein Array.
Some(array)
}
Rust verlangt nicht, dass du das Schlüsselwort return (opens in a new tab) verwendest, wenn du am Ende einer Funktion einen Wert zurückgibst.
#[wasm_bindgen]
pub fn wasm_generate_stealth_address(stealth_address: &str) -> Option<String> {
Diese Funktion empfängt eine öffentliche Meta-Adresse, die sowohl Vpub als auch Kpub enthält. Sie gibt die Stealth-Adresse, den zu veröffentlichenden öffentlichen Schlüssel (Rpub) und einen Ein-Byte-Scanwert zurück, der die Identifizierung beschleunigt, welche veröffentlichten Adressen zu Alice gehören könnten.
Der Scanwert ist Teil des gemeinsamen Geheimnisses (S = GRprivVpriv). Dieser Wert steht Alice zur Verfügung, und seine Überprüfung ist viel schneller als die Überprüfung, ob f(Kpub+G*hash(S)) der veröffentlichten Adresse entspricht.
let (address, r_pub, scan) =
generate_stealth_address(&str_to_array::<66>(stealth_address)?);
Wir verwenden die generate_stealth_address (opens in a new tab) der Bibliothek.
format!("{{\"address\":\"{}\",\"rPub\":\"{}\",\"scan\":\"{}\"}}",
encode(address),
encode(r_pub),
encode(&[scan])
).into()
}
Bereite den JSON-kodierten Ausgabe-String vor.
#[wasm_bindgen]
pub fn wasm_compute_stealth_key(
address: &str,
bill_pub_key: &str,
view_private_key: &str,
spend_private_key: &str
) -> Option<String> {
.
.
.
}
Diese Funktion verwendet die compute_stealth_key (opens in a new tab) der Bibliothek, um den privaten Schlüssel zum Abheben von der Adresse (Rpriv) zu berechnen. Diese Berechnung erfordert diese Werte:
- Die Adresse (Adresse=f(Ppub))
- Den von Bill generierten öffentlichen Schlüssel (Rpub)
- Den privaten Ansichtsschlüssel (Vpriv)
- Den privaten Ausgabeschlüssel (Kpriv)
#[wasm_bindgen(start)]
#[wasm_bindgen(start)] (opens in a new tab) gibt an, dass die Funktion ausgeführt wird, wenn der WASM-Code initialisiert wird.
pub fn main() {
console_error_panic_hook::set_once();
}
Dieser Code legt fest, dass die Panic-Ausgabe an die JavaScript-Konsole gesendet wird. Um dies in Aktion zu sehen, verwende die Anwendung und gib Bill eine ungültige Meta-Adresse (ändere einfach eine hexadezimale Ziffer). Du wirst diesen Fehler in der JavaScript-Konsole sehen:
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
Gefolgt von einem Stacktrace. Gib Bill dann die gültige Meta-Adresse und gib Alice entweder eine ungültige Adresse oder einen ungültigen öffentlichen Schlüssel. Du wirst diesen Fehler sehen:
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
Wieder gefolgt von einem Stacktrace.
Die Benutzeroberfläche
Die Benutzeroberfläche ist mit React (opens in a new tab) geschrieben und wird von Vite (opens in a new tab) bereitgestellt. Du kannst mehr darüber in diesem Tutorial erfahren. Hier besteht kein Bedarf für Wagmi (opens in a new tab), da wir nicht direkt mit einer Blockchain oder einer Wallet interagieren.
Der einzige nicht offensichtliche Teil der Benutzeroberfläche ist die WASM-Konnektivität. Hier ist, wie sie funktioniert.
vite.config.js
Diese Datei enthält die Vite-Konfiguration (opens in a new tab).
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()],
})
Wir benötigen zwei Vite-Plugins: react (opens in a new tab) und wasm (opens in a new tab).
App.jsx
Diese Datei ist die Hauptkomponente der Anwendung. Sie ist ein Container, der zwei Komponenten enthält: Alice und Bill, die Benutzeroberflächen für diese Benutzer. Der relevante Teil für WASM ist der Initialisierungscode.
import init from './rust-wasm/pkg/rust_wasm.js'
Wenn wir wasm-pack (opens in a new tab) verwenden, erstellt es zwei Dateien, die wir hier verwenden: eine wasm-Datei mit dem eigentlichen Code (hier src/rust-wasm/pkg/rust_wasm_bg.wasm) und eine JavaScript-Datei mit den Definitionen zu deren Verwendung (hier src/rust_wasm/pkg/rust_wasm.js). Der Standardexport (Default Export) dieser JavaScript-Datei ist Code, der ausgeführt werden muss, um WASM zu initiieren.
function App() {
.
.
.
useEffect(() => {
const loadWasm = async () => {
try {
await init();
setWasmReady(true)
} catch (err) {
console.error('Error loading wasm:', err)
alert("Wasm error: " + err)
}
}
loadWasm()
}, []
)
Der useEffect-Hook (opens in a new tab) lässt dich eine Funktion angeben, die ausgeführt wird, wenn sich Zustandsvariablen ändern. Hier ist die Liste der Zustandsvariablen leer ([]), sodass diese Funktion nur einmal beim Laden der Seite ausgeführt wird.
Die Effekt-Funktion muss sofort zurückkehren. Um asynchronen Code zu verwenden, wie z. B. das WASM-init (das die .wasm-Datei laden muss und daher Zeit benötigt), definieren wir eine interne async (opens in a new tab)-Funktion und führen sie ohne ein await aus.
Bill.jsx
Dies ist die Benutzeroberfläche für Bill. Sie hat eine einzige Aktion: das Erstellen einer Adresse basierend auf der von Alice bereitgestellten Stealth-Meta-Adresse.
import { wasm_generate_stealth_address } from './rust-wasm/pkg/rust_wasm.js'
Zusätzlich zum Standardexport exportiert der von wasm-pack generierte JavaScript-Code eine Funktion für jede Funktion im WASM-Code.
<button onClick={() => {
setPublicAddress(JSON.parse(wasm_generate_stealth_address(stealthMetaAddress)))
}}>
Um WASM-Funktionen aufzurufen, rufen wir einfach die Funktion auf, die von der durch wasm-pack erstellten JavaScript-Datei exportiert wurde.
Alice.jsx
Der Code in Alice.jsx ist analog, außer dass Alice zwei Aktionen hat:
- Eine Meta-Adresse generieren
- Den privaten Schlüssel für eine von Bill veröffentlichte Adresse abrufen
Fazit
Stealth-Adressen sind kein Allheilmittel; sie müssen korrekt verwendet werden. Aber wenn sie richtig eingesetzt werden, können sie Privatsphäre auf einer öffentlichen Blockchain ermöglichen.
Weitere meiner Arbeiten findest du hier (opens in a new tab).