
Privasi di Solana dengan Elusiv dan Light: Semua yang Perlu Anda Ketahui Tentang Privasi di SOL
Daftar Isi
- Prasyarat
- Apa yang dibahas dalam artikel ini?
- Privasi Itu Penting
- Semua Orang Perlu Peduli terhadap Privasi
- Apa itu Elusiv?
- Bagaimana cara kerja Elusiv?
- Apa itu Light Protocol?
- Bagaimana cara kerja Light Protocol?
- Mengirim SOL Secara Privat Menggunakan Elusiv
- Kode Lengkap
- Menguraikan Kode Elusiv
- Mengirim SOL Secara Privat Menggunakan Light Protocol
- Kode Lengkap
- Menguraikan Kode
- Kesimpulan
- Referensi Tambahan / Bacaan Lebih Lanjut
Prasyarat
- Node.js sudah terinstal (untuk menginstal dependensi yang diperlukan, menjalankan skrip, dan mengirim $SOL secara privat)
- Pemahaman dasar tentang TypeScript
- Pemahaman dasar tentang @solana/web3.js
Apa yang dibahas dalam artikel ini?
Privasi merupakan inti dari teknologi blockchain modern. Sistem ledger publik, transaksi, saldo akun, dan sering kali kode sumber program tersedia secara terbuka agar dapat dilihat siapa saja. Meskipun tingkat transparansi yang belum pernah ada sebelumnya ini dianggap sebagai salah satu ciri utama teknologi blockchain, privasi dapat menjadi kebutuhan penting bagi banyak aplikasi atau penggunaan sehari-hari.
Elusiv dan Light Protocol menawarkan solusi mutakhir untuk privasi di Solana dengan memanfaatkan zk-SNARKS bagi transaksi privat, program privat, dan solusi kepatuhan terdesentralisasi. Dalam artikel ini, kami membahas pentingnya privasi, menelusuri alasan blockchain seperti Solana memerlukan fitur privasi, dan memberikan panduan langkah demi langkah untuk mengirim SOL secara privat menggunakan TypeScript SDK milik Elusiv dan modul zk.js milik Light.
Privasi Itu Penting
Privasi adalah hak asasi manusia yang penting bagi otonomi dan terjaganya martabat manusia. Privasi diperlukan dalam masyarakat yang bebas dan terbuka karena mendasari pelaksanaan hak-hak lain, seperti kebebasan berbicara dan kebebasan berserikat. Hal ini memungkinkan terciptanya ruang yang terpisah dari kehidupan politik, sehingga siapa pun dapat berpikir, berbicara, menyampaikan gagasan, atau bertindak tanpa terus-menerus diawasi oleh pihak ketiga. Kontroversi publik baru-baru ini, seperti pengungkapan Edward Snowden, informasi yang dipublikasikan WikiLeaks, dan skandal data Facebook-Cambridge Analytica, telah memicu perdebatan sengit mengenai pentingnya dan batas-batas privasi.
Semua Orang Perlu Peduli terhadap Privasi
Sekilas, mungkin tampak berlawanan dengan intuisi jika kita berpendapat bahwa ledger publik, yang dibangun di atas teknologi terdesentralisasi dengan transparansi sebagai salah satu prinsip dasarnya, seharusnya memiliki fitur pendukung privasi. Baik Anda seorang cypherpunk sejati maupun pengguna biasa, semua orang perlu peduli terhadap privasi. Anda mungkin berpikir bahwa karena tidak melakukan sesuatu yang berbahaya atau ilegal secara online, tidak masalah jika orang lain melihat aktivitas Anda di blockchain. Pertimbangkan eksperimen pemikiran berikut:
Kita memiliki dua karakter: Alice, pengguna biasa yang menghargai privasinya dan ingin melakukan pembelian tanpa diawasi; serta pelaku jahat, yang akan saya singkat sebagai MA. Pelaku jahat dapat berupa pemerintah yang represif, pemberi kerja yang mengontrol, atau penjahat siber. Misalnya, Alice tinggal di negara yang pemerintahnya terus-menerus mengawasi setiap warga, atau Alice bekerja di perusahaan yang memiliki kebijakan ketat terhadap pembelian legal tertentu (misalnya, donasi politik atau membeli buku tentang topik tertentu). Suatu hari, Alice melakukan pembelian menggunakan blockchain tradisional seperti Solana karena menganggapnya sebagai metode pembayaran yang aman dan privat. Urutan peristiwanya adalah sebagai berikut:
- Transaksi Alice dicatat di ledger publik. Transaksinya mencakup kunci publik Alice, kunci publik penerima, dan jumlah yang dikirim
- MA, yang ingin memantau atau mengontrol perilaku Alice, mulai melacak transaksinya menggunakan kunci publik Alice
- MA menemukan pembelian Alice, yang dianggap "tidak pantas" menurut aturan mereka
- MA mengambil tindakan terhadap Alice yang, tergantung situasinya, dapat berupa tuntutan hukum, pemenjaraan, sanksi di tempat kerja, penghukuman sosial, atau pemerasan
Eksperimen pemikiran ini menggambarkan kenyataan nyata tentang dampak kurangnya privasi di blockchain terhadap pengguna biasa. Seiring munculnya para penyelidik on-chain dan teknologi berbahaya untuk memanen data, pelacakan transaksi pengguna biasa menjadi sangat mudah dan dapat menimbulkan konsekuensi besar di dunia nyata. Di dunia yang semakin digital, tanpa privasi kita berisiko kehilangan kedaulatan individu, membiarkan semua keputusan kita diawasi, dan menjadikan setiap aspek keberadaan kita sebagai komoditas. Blockchain hanya akan mempercepat hal ini jika kita tidak menerapkan teknologi pendukung privasi. Di sinilah Elusiv dan Light Protocol berperan.
Apa itu Elusiv?
Elusiv mendeskripsikan dirinya sebagai "protokol privasi berbasis blockchain dengan zero-knowledge" yang "memungkinkan pengguna dan aplikasi mengakses enkripsi universal". Elusiv berupaya mewujudkan privasi tanpa mengorbankan keamanan, keselamatan, dan desentralisasi dengan menerapkan kriptografi zero-knowledge serta komputasi multipihak pada pengguna dan jaringan. Sasaran enkripsi universal ini memungkinkan Elusiv menyediakan alat yang memberi pengguna kendali atas data mereka. Kini, pengguna dapat memilih apa yang dibagikan di blockchain dan apa yang tidak.
Bagaimana cara kerja Elusiv?
Elusiv bekerja dengan meminta pengguna mengirim dana ke pool bersama yang dikelola program Elusiv, yang akan mengisi saldo privat mereka. Dari pool tersebut, pengguna dapat mengirim dan menerima token seperti SOL, serta menarik dana. Perlu diperhatikan bahwa dengan model pool bersama ini, orang lain masih dapat mengamati setoran ke dan pembayaran dari Elusiv. Namun, seiring bertambahnya pengguna dan transaksi, menghubungkan setoran dan pembayaran ke akun tertentu menjadi semakin sulit dari waktu ke waktu—lebih mudah menghubungkan satu-satunya pengguna yang menyetor 10 SOL dan menarik 10 SOL dibandingkan menghubungkan salah satu dari jutaan pengguna yang melakukan setoran dan pembayaran bertahap. Anonimitas membutuhkan banyak pengguna.
Dana di dalam pool tidak memuat informasi apa pun tentang penyetornya. Namun, dengan menggunakan bukti zero-knowledge, nilai rahasia dikaitkan dengan dana pengguna sehingga bukti otoritas dapat dibuat atas dana yang belum dibelanjakan. Bukti zero-knowledge yang digunakan di Elusiv dikenal sebagai zk-SNARKS (Zero-Knowledge Succinct Non-Interactive Argument of Knowledge). Tanpa membahas kompleksitas bukti zk-SNARK secara mendalam, anggaplah bukti tersebut sebagai cara yang terbukti secara matematis untuk menunjukkan kepada teman bahwa Anda mengetahui kata sandi rahasia tanpa pernah memberitahukan kata sandi itu. Teman Anda dapat dengan cepat memeriksa bahwa Anda berkata benar tanpa perlu menanyakan hal lain. Dengan demikian, Elusiv dapat melacak dana Anda yang belum dibelanjakan tanpa memberi tahu seluruh Solana berapa banyak dana yang Anda miliki di dalam pool. Jika tertarik mempelajari lebih lanjut tentang Bukti Zero-Knowledge, saya sangat menyarankan Anda mengikuti kelas Porter tentang Bukti Zero-Knowledge.
Apa itu Light Protocol?
Light Protocol mendeskripsikan dirinya sebagai "zkLayer generasi berikutnya di Solana" yang memungkinkan eksekusi program privat secara langsung di Solana. Ada tiga konsep mendasar pada Light yang memungkinkan privasi di Solana:
- State privat
- Model UTXO
- Verifikasi transisi state privat secara on-chain
Bagaimana cara kerja Light Protocol?
Light Protocol memungkinkan state on-chain dienkripsi. Dalam hal ini, pengguna "memiliki" state tersebut dan mempunyai hak dekripsi eksklusif. Berbeda dengan pendekatan pool dana milik Elusiv, Light Protocol memperkenalkan model UTXO (Unspent Transaction Outputs) ke Solana. UTXO terikat pada keypair terlindung dan dapat menyimpan dua saldo, satu dalam SOL (karena merupakan token biaya di Light Protocol) dan satu dalam token SPL lainnya. Dengan pendekatan ini, setiap transaksi menghasilkan UTXO baru yang ditambahkan ke daftar linear sehingga menghindari pembaruan langsung; state disembunyikan agar tidak membocorkan informasi tentang state mana yang diperbarui dan siapa yang memperbaruinya.
Logika program di Solana hampir selalu berupa escrow dengan sejumlah batasan unik. Light Protocol menghadirkan inovasi pada desain ini dengan mengodekan logika program ke dalam sirkuit zero-knowledge (zk-SNARKS) di sisi klien, tempat komputasi dan bukti dihasilkan. Bukti ini dibagikan secara on-chain, lalu program verifier khusus yang dibuat untuk sirkuit tersebut memeriksa validitasnya. Setelah verifikasi berhasil, Program verifier khusus memanggil verifier native lain yang menyelesaikan berbagai pemeriksaan keamanan dan menambahkan commitment baru ke program Merkle tree milik Light.
Meskipun berada di luar cakupan artikel ini, Light memungkinkan Anda membuat Private Solana Program (PSP) khusus sendiri dari awal. Sebaiknya baca seluruh artikel ini dan lihat dokumentasi mereka sebelum mencoba membuatnya sendiri. Dokumentasi tersebut mencakup tutorial membuat PSP khusus Anda sendiri, yang dapat ditemukan di sini.
Semua ini memang menarik, tetapi bagaimana saya dapat menerapkannya secara langsung untuk pemrograman di Solana?
Mengirim SOL Secara Privat Menggunakan Elusiv
Kode Lengkap
import * as ed from "@noble/ed25519";
import { sha512 } from "@noble/hashes/sha512";
ed.etc.sha512Sync = (...m) => sha512(ed.etc.concatBytes(...m));
import {
Connection,
PublicKey,
Keypair,
ConfirmedSignatureInfo,
Cluster,
LAMPORTS_PER_SOL,
clusterApiUrl,
} from "@solana/web3.js";
import { Elusiv, TokenType, SEED_MESSAGE } from "@elusiv/sdk";
const CLUSTER: Cluster = "devnet";
const RPC = "https://rpc-devnet.helius.xyz";
const main = async () => {
const connection: Connection = new Connection(RPC);
const keyPair: Keypair = generateKeypair();
const recipientPublicKey: PublicKey = new PublicKey(generateKeypair().publicKey);
await airdropSol(keyPair);
const seed: Uint8Array = ed.sign(Buffer.from(SEED_MESSAGE, "utf-8"), keyPair.secretKey.slice(0, 32));
const elusiv: Elusiv = await Elusiv.getElusivInstance(seed, keyPair.publicKey, connection, CLUSTER);
const balance: bigint = await elusiv.getLatestPrivateBalance("LAMPORTS");
try {
if (balance > BigInt(0)) {
const signature = await send(elusiv, recipientPublicKey, 1 * LAMPORTS_PER_SOL, "LAMPORTS");
console.log(`Sent with signature ${signature.signature}`);
} else {
console.log("Private balance is empty. Topping up...");
const amount = 1 * LAMPORTS_PER_SOL;
const tokenType = "LAMPORTS";
const topUpTxData = await elusiv.buildTopUpTx(amount, tokenType);
topUpTxData.tx.partialSign(keyPair);
const topUpSig: ConfirmedSignatureInfo = await elusiv.sendElusivTx(topUpTxData);
console.log(`Top-up complete with signature ${topUpSig.signature}`);
const signature: ConfirmedSignatureInfo = await send(elusiv, recipientPublicKey, 1 * LAMPORTS_PER_SOL, "LAMPORTS");
console.log(`Sent with signature ${signature.signature}`);
}
} catch (e) {
console.error(`Error sending SOL via Elusiv: ${e}`);
} finally {
console.log("Exiting program...");
process.exit(0);
}
};
const send = async (
elusiv: Elusiv,
recipient: PublicKey,
amount: number,
tokenType: TokenType
): Promise => {
const txt = await elusiv.buildSendTx(amount, recipient, tokenType);
return elusiv.sendElusivTx(txt);
};
const generateKeypair = (): Keypair => {
let keyPair = Keypair.generate();
console.log(`Public key: ${keyPair.publicKey.toBase58()}`);
console.log(`Private key: ${keyPair.secretKey}`);
return keyPair;
};
const airdropSol = async (wallet: Keypair) => {
try {
const connection = new Connection(clusterApiUrl("devnet"));
const airdropSignature = await connection.requestAirdrop(new PublicKey(wallet.publicKey), 1 * LAMPORTS_PER_SOL);
const latestBlockHash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
blockhash: latestBlockHash.blockhash,
lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
signature: airdropSignature,
});
console.log(`Airdropped 1 SOL to ${wallet.publicKey.toBase58()}`);
} catch (e) {
console.error(`Error sending SOL via Elusiv: ${e}`);
}
};
main();Menguraikan Kode Elusiv
import * as ed from "@noble/ed25519";
import { sha512 } from "@noble/hashes/sha512";
ed.etc.sha512Sync = (...m) => sha512(ed.etc.concatBytes(...m));Pertama, kita mengimpor library noble-ed25519 karena belum menyiapkan konektivitas wallet. Dalam lingkungan produksi, Anda akan menggunakan Solana Wallet Adapter untuk menandatangani transaksi. Di sini, kita hanya memerlukan fungsionalitas sign. Namun, penggunaan import { sign } from "@noble/ed25519"; terkadang dapat menampilkan error bahwa etc.sha512Sync belum ditetapkan. Untuk menghindari error ini, kita menetapkannya sendiri—Anda tidak perlu terlalu mengkhawatirkan hal ini.
import {
Connection,
PublicKey,
Keypair,
ConfirmedSignatureInfo,
Cluster,
LAMPORTS_PER_SOL,
clusterApiUrl,
} from "@solana/web3.js";
import { Elusiv, TokenType, SEED_MESSAGE } from "@elusiv/sdk";Kemudian, kita mengimpor web3.js milik Solana dan TypeScript SDK milik Elusiv beserta modul yang diperlukan.
const CLUSTER: Cluster = "devnet";
const RPC = "https://rpc-devnet.helius.xyz";Di sini, kita menetapkan CLUSTER sebagai "devnet" dan mengatur RPC ke RPC devnet Helius. Jika ingin menggunakan skrip ini di mainnet, Anda perlu menetapkan CLUSTER sebagai "mainnet" dan mendapatkan kunci API Helius dari salah satu paket berikut 😎
const main = async () => {
const connection: Connection = new Connection(RPC);
const keyPair: Keypair = generateKeypair();
const recipientPublicKey: PublicKey = new PublicKey(generateKeypair().publicKey);
// Rest of the code
}Kita menandai fungsi main sebagai asinkron karena kita menjalankan await pada beberapa fungsi di dalam bloknya. Kemudian, kita membuat koneksi ke devnet menggunakan RPC dan membuat objek Keypair dari fungsi utilitas generateKeypair. Kita juga membuat recipientPublicKey dengan fungsi generateKeypair tersebut agar dapat menerima SOL terlindung di alamat acak. Sebagai referensi, fungsi generateKeypair didefinisikan sebagai berikut:
const generateKeypair = (): Keypair => {
let keyPair = Keypair.generate();
console.log(`Public key: ${keyPair.publicKey.toBase58()}`);
console.log(`Private key: ${keyPair.secretKey}`);
return keyPair;
};Fungsi ini membuat keypair pengujian Solana yang akan kita gunakan untuk skrip ini. Jika ingin menggunakannya di mainnet, Anda perlu mengganti keypair tersebut dengan keypair wallet Anda sendiri. Ingat, jangan pernah menyimpan kunci privat dalam teks biasa dan pastikan untuk mengimpornya dengan benar menggunakan path file yang tepat.
await airdropSol(keyPair);Kita memerlukan SOL devnet karena menggunakan keypair pengujian yang baru dibuat. Kita menggunakan fungsi utilitas aidropSol untuk melakukan airdrop SOL ke keypair baru kita, yang didefinisikan sebagai berikut:
const airdropSol = async (wallet: Keypair) => {
try {
const connection = new Connection(clusterApiUrl("devnet"));
const airdropSignature = await connection.requestAirdrop(new PublicKey(wallet.publicKey), 1 * LAMPORTS_PER_SOL);
const latestBlockHash = await connection.getLatestBlockhash();
await connection.confirmTransaction({
blockhash: latestBlockHash.blockhash,
lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
signature: airdropSignature,
});
console.log(`Airdropped 1 SOL to ${wallet.publicKey.toBase58()}`);
} catch (e) {
console.error(`Error sending SOL via Elusiv: ${e}`);
}
};Di sini, kita melakukan airdrop 1 SOL (1 * LAMPORTS_PER_SOL) kepada diri sendiri di devnet. Kita mengambil latestBlockHash agar dapat meneruskan blockhash dan tinggi blok valid terakhir ke connection.confirmTransaction(), sehingga mengonfirmasi bahwa kita telah melakukan airdrop 1 SOL ke alamat yang benar.
const seed: Uint8Array = ed.sign(Buffer.from(SEED_MESSAGE, "utf-8"), keyPair.secretKey.slice(0, 32));Elusiv memerlukan seed input untuk memastikan operasi tertentu bersifat deterministik. Karena itu, kita mengimpor dan menggunakan SEED_MESSAGE. SEED_MESSAGE adalah pesan wajib yang harus ditandatangani karena digunakan untuk menghasilkan seed Elusiv; pesan ini memungkinkan aplikasi mendekripsi aset privat Anda beserta nilai rahasia terkait agar Anda dapat melacak dana. Kita menggunakan Buffer.from() untuk membuat buffer baru (struktur data biner mentah) dari SEED_MESSAGE dengan encoding utf-8. Kita perlu menggunakan slice karena tipe keypair Solana menyimpan kunci privat pada 32 byte pertama dan kunci publik pada 32 byte terakhir. Dengan demikian, kita menandatangani pesan seed yang diwajibkan menggunakan kunci privat.
const elusiv: Elusiv = await Elusiv.getElusivInstance(seed, keyPair.publicKey, connection, CLUSTER);Di sini, kita menetapkan elusiv, yaitu instance Elusiv, menggunakan seed, keyPair.publicKey, connection, dan CLUSTER. Dengan demikian, kita membuat instance Elusiv di devnet menggunakan RPC devnet, kunci publik, dan pesan panjang yang baru saja ditandatangani.
const balance: bigint = await elusiv.getLatestPrivateBalance("LAMPORTS");Kemudian, kita mengambil saldo privat—jumlah Lamport yang kita miliki dalam pool Elusiv—yang dikembalikan sebagai BigInt. Bagian lain dari fungsi main dibungkus dalam try-catch-finally block, yang didefinisikan sebagai berikut:
try {
if (balance > BigInt(0)) {
const signature = await send(elusiv, recipientPublicKey, 1 * LAMPORTS_PER_SOL, "LAMPORTS");
console.log(`Sent with signature ${signature.signature}`);
} else {
// Rest of code
}
}Jika kita memiliki saldo privat, balance akan lebih besar dari 0 dan blok pertama pada blok if-else akan dieksekusi. Alasan kita mengonversi 0 menjadi BigInt dalam kondisi if adalah karena tipe nilai kembalian getLatestPrivateBalance adalah BigInt. Setelah itu, kita membuat signature, yaitu variabel yang ditetapkan ke nilai kembalian send(). Fungsi send() didefinisikan sebagai berikut:
const send = async (
elusiv: Elusiv,
recipient: PublicKey,
amount: number,
tokenType: TokenType
): Promise => {
const txt = await elusiv.buildSendTx(amount, recipient, tokenType);
return elusiv.sendElusivTx(txt);
};Fungsi ini mengirim transaksi melalui Elusiv dan mengembalikan Promise bertipe ConfirmedSignatureInfo (signature terkonfirmasi beserta statusnya). Sebagai argumen, kita menerima instance Elusiv, kunci publik penerima, jumlah yang akan dikirim, dan jenis token (tidak harus Lamport dan dapat berupa berbagai token lain seperti USDC, USDT, mSOL, BONK, dan SAMO). Kemudian, kita menetapkan txt menggunakan elusiv.buildSendTx(). buildSendTx() adalah method pada instance Elusiv yang membuat transaksi untuk mengirim token kepada penerima tertentu menggunakan saldo privat. Kemudian, kita mengirim dan mengembalikan transaksi menggunakan pernyataan return elusiv.sendElusivTx(txt) dengan meneruskan transaksi yang telah dibuat, yaitu txt.
Jika tidak memiliki saldo privat, blok else akan dieksekusi:
console.log("Private balance is empty. Topping up...");
const amount = 1 * LAMPORTS_PER_SOL;
const tokenType = "LAMPORTS";
const topUpTxData = await elusiv.buildTopUpTx(amount, tokenType);
topUpTxData.tx.partialSign(keyPair);
const topUpSig: ConfirmedSignatureInfo = await elusiv.sendElusivTx(topUpTxData);
console.log(`Top-up complete with signature ${topUpSig.signature}`);
const signature: ConfirmedSignatureInfo = await send(elusiv, recipientPublicKey, 1 * LAMPORTS_PER_SOL, "LAMPORTS");
console.log(`Sent with signature ${signature.signature}`);Kita memberi tahu pengguna melalui log bahwa mereka tidak memiliki saldo privat dan kita akan mengisinya. Kemudian, kita membuat transaksi pengisian menggunakan method .buildTopUpTx() pada instance Elusiv. Kita meneruskan nilai 1 SOL dan jenis token Lamport karena kita mengirim SOL. Selanjutnya, kita menandatangani pengisian dengan .partialSign() pada keypair transaksi karena pengisian dilakukan dari kunci publik kita. Lalu, kita mengirim transaksi yang telah dibuat menggunakan elusiv.sendElusivTx(topUpTxData) dan mencatat signature transaksi.
Bagian lain dari blok try-catch-finally adalah sebagai berikut:
} catch (e) {
console.error(`Error sending SOL via Elusiv: ${e}`);
} finally {
console.log("Exiting program...");
process.exit(0);
}Jika terjadi error saat mengirim SOL melalui Elusiv, kita mencatatnya ke konsol menggunakan console.error(). Kemudian, kita keluar dari program menggunakan process.exit(0).
Untuk memulai seluruh proses ini, kita memanggil fungsi main() di bagian bawah file.
Mengirim SOL Secara Privat Menggunakan Light Protocol
Kode Lengkap
import { BN } from "@coral-xyz/anchor";
import { PublicKey, Keypair, Connection } from "@solana/web3.js";
import { User, Provider as LightProvider, TestRelayer, confirmConfig, airdropSol } from "@lightprotocol/zk.js";
const initializeSolanaWallet = async (): Promise => {
const wallet = Keypair.generate();
console.log("Wallet initialized");
return wallet;
};
const requestAirdrop = async (connection: Connection, publicKey: PublicKey): Promise => {
await airdropSol({
connection,
lamports: 2e9,
recipientPublicKey: publicKey,
});
console.log("Airdrop requested...");
};
const setupTestRelayer = async (solanaWallet: Keypair): Promise => {
const testRelayer = new TestRelayer({
relayerPubkey: solanaWallet.publicKey,
relayerRecipientSol: solanaWallet.publicKey,
relayerFee: new BN(100_000),
payer: solanaWallet,
});
console.log("Test relayer initialized");
return testRelayer;
};
const initializeLightProvider = async (solanaWallet: Keypair, testRelayer: TestRelayer): Promise => {
const lightProvider = await LightProvider.init({
wallet: solanaWallet,
relayer: testRelayer,
confirmConfig,
});
console.log("Light provider initialized");
return lightProvider;
};
const initializeLightUser = async (lightProvider: LightProvider): Promise => {
const user = await User.init({ provider: lightProvider });
console.log("Light user initialized");
return user;
};
const performShieldOperation = async (user: User) => {
await user.shield({
publicAmountSol: "1.1",
token: "SOL",
});
console.log("Performed shield operation");
};
const executePrivateTransfer = async (user: User, testRecipientPublicKey: string) => {
const response = await user.transfer({
amountSol: "1",
token: "SOL",
recipient: testRecipientPublicKey,
});
console.log(`Executed private transfer! Txt hash: ${response.txHash}`);
};
const main = async () => {
try {
const solanaWallet = await initializeSolanaWallet();
const connection = new Connection("http://127.0.0.1:8899");
await requestAirdrop(connection, solanaWallet.publicKey);
const testRelayer = await setupTestRelayer(solanaWallet);
const lightProvider = await initializeLightProvider(solanaWallet, testRelayer);
const user = await initializeLightUser(lightProvider);
await performShieldOperation(user);
const testRecipientKeypair = Keypair.generate();
await requestAirdrop(connection, testRecipientKeypair.publicKey);
const lightProviderRecipient = await initializeLightProvider(testRecipientKeypair, testRelayer);
const testRecipient = await initializeLightUser(lightProviderRecipient);
await executePrivateTransfer(user, testRecipient.account.getPublicKey());
console.log(`Successfully sent 1 $SOL to ${testRecipient.account.getPublicKey()} privately!`);
} catch (e) {
console.error(`Error sending SOL via Light: ${e}`);
} finally {
console.log("Exiting program...");
process.exit(0);
}
};
main();Menguraikan Kode
import { BN } from "@coral-xyz/anchor";
import { PublicKey, Keypair, Connection } from "@solana/web3.js";
import { User, Provider as LightProvider, TestRelayer, confirmConfig, airdropSol } from "@lightprotocol/zk.js";Pertama, kita mengimpor modul yang diperlukan dari Anchor, Solana/web3.js, dan Light untuk berinteraksi dengan Solana menggunakan Light Protocol. Kemudian, kita menetapkan sejumlah fungsi utilitas sebelum masuk ke fungsi main—Light memiliki proses inisialisasi yang lebih kompleks dibandingkan implementasi Elusiv kita.
const initializeSolanaWallet = async (): Promise => {
const wallet = Keypair.generate();
console.log("Wallet initialized");
return wallet;
};Di sini, kita membuat fungsi initializeSolanaWallet, yang menghasilkan wallet Solana baru menggunakan method Keypair.generate().
const requestAirdrop = async (connection: Connection, publicKey: PublicKey): Promise => {
await airdropSol({
connection,
lamports: 2e9,
recipientPublicKey: publicKey,
});
console.log("Airdrop requested...");
};Berbeda dengan Elusiv, Light menyediakan fungsi airdropSol di library mereka untuk melakukan airdrop Lamport ke kunci publik tertentu. Kita membuat fungsi utilitas requestAirdrop untuk mengirim SOL ke publicKey yang diteruskan.
const setupTestRelayer = async (solanaWallet: Keypair): Promise => {
const testRelayer = new TestRelayer({
relayerPubkey: solanaWallet.publicKey,
relayerRecipientSol: solanaWallet.publicKey,
relayerFee: new BN(100_000),
payer: solanaWallet,
});
console.log("Test relayer initialized");
return testRelayer;
};Untuk mengirim SOL terlindung melalui Light, kita perlu menyiapkan relayer pengujian menggunakan modul TestRelayer. Relayer berperan penting dalam ekosistem Light karena merupakan server web yang meneruskan bukti ZK, yang membuktikan transisi state, dari klien ke program on-chain terkait. Relayer juga membayar biaya transaksi dan menerima biaya sebagai imbalan setelah verifikasi bukti berhasil. Biayanya adalah 100 ribu Lamport, yang kita tetapkan dengan new BN(100_000).
const initializeLightProvider = async (solanaWallet: Keypair, testRelayer: TestRelayer): Promise => {
const lightProvider = await LightProvider.init({
wallet: solanaWallet,
relayer: testRelayer,
confirmConfig,
});
console.log("Light provider initialized");
return lightProvider;
};Kemudian, kita menginisialisasi Light Provider dengan fungsi yang diberi nama sesuai tujuannya, yaitu initializeLightProvider(). Fungsi ini menyiapkan provider dan menghubungkannya dengan wallet Solana serta relayer pengujian menggunakan konfigurasi yang disediakan Light, yaitu confirmConfig—konfigurasi ini bertipe ConfirmOptions dan menangani langkah verifikasi transaksi, tingkat commitment, dan sebagainya.
const initializeLightUser = async (lightProvider: LightProvider): Promise => {
const user = await User.init({ provider: lightProvider });
console.log("Light user initialized");
return user;
};Fungsi initializeLightUser cukup jelas—fungsi ini menginisialisasi pengguna untuk Light Protocol menggunakan lightProvider yang diteruskan.
const performShieldOperation = async (user: User) => {
await user.shield({
publicAmountSol: "1.1",
token: "SOL",
});
console.log("Performed shield operation");
};Fungsi performShieldOperation memungkinkan pengguna melindungi SOL sehingga menjadi privat. Di sini, kita melindungi lebih dari 1 SOL, meskipun hanya mengirim 1 SOL terlindung, untuk memperhitungkan biaya.
const executePrivateTransfer = async (user: User, testRecipientPublicKey: string) => {
const response = await user.transfer({
amountSol: "1",
token: "SOL",
recipient: testRecipientPublicKey,
});
console.log(`Executed private transfer! Txt hash: ${response.txHash}`);
};Ini dapat dianggap sebagai fungsi utilitas terpenting karena benar-benar mengeksekusi transfer privat. Di sini, kita mentransfer 1 SOL secara privat dari user ke penerima tertentu, yaitu testRecipientPublicKey.
const main = async () => {
try {
const solanaWallet = await initializeSolanaWallet();
const connection = new Connection("http://127.0.0.1:8899");
await requestAirdrop(connection, solanaWallet.publicKey);
const testRelayer = await setupTestRelayer(solanaWallet);
const lightProvider = await initializeLightProvider(solanaWallet, testRelayer);
const user = await initializeLightUser(lightProvider);
await performShieldOperation(user);
const testRecipientKeypair = Keypair.generate();
await requestAirdrop(connection, testRecipientKeypair.publicKey);
const lightProviderRecipient = await initializeLightProvider(testRecipientKeypair, testRelayer);
const testRecipient = await initializeLightUser(lightProviderRecipient);
await executePrivateTransfer(user, testRecipient.account.getPublicKey());
console.log(`Successfully sent 1 $SOL to ${testRecipient.account.getPublicKey()} privately!`);
} catch (e) {
console.error(`Error sending SOL via Light: ${e}`);
} finally {
console.log("Exiting program...");
process.exit(0);
}
};Fungsi main berfungsi sebagai titik masuk skrip kita. Kita menandainya sebagai asinkron karena ada sejumlah fungsi async yang dipanggil di dalam cakupannya. Fungsi ini menjalankan semua langkah secara berurutan, dimulai dengan inisialisasi wallet dan diakhiri dengan eksekusi transfer privat. Pertama, kita menyiapkan wallet dan koneksi Solana. Kemudian, kita melakukan airdrop SOL ke wallet dan menginisialisasi relayer serta Light Provider. Selanjutnya, kita menginisialisasi wallet sebagai Light User dan melindungi SOL. Setelah itu, kita membuat penerima pengujian, melakukan airdrop sejumlah SOL kepada penerima tersebut, menginisialisasinya sebagai Light User, dan mengirim 1 SOL secara privat. Seperti kode Elusiv, kita menempatkan logika di dalam blok try-catch-finally untuk menangkap error dan secara otomatis keluar dari program setelah selesai.
Anda mungkin memperhatikan bahwa, berbeda dengan Elusiv yang menggunakan devnet, di sini kita mengatur koneksi ke "http://127.0.0.1:8899". Saat artikel ini ditulis, perlu diperhatikan bahwa Light Protocol belum diterapkan di devnet/mainnet sehingga kunci Helius belum dapat digunakan (untuk saat ini 👀). Untuk localhost, Anda perlu menjalankan test-validator dengan akun dan program yang diperlukan telah dimuat sebelumnya agar dapat menjalankan kode. Anda dapat menginstal Light Protocol CLI untuk melakukannya, lalu menjalankan perintah berikut:
light test-validatorTindakan ini akan menjalankan validator di latar belakang. Saat ini, Anda juga perlu menambahkan chai (library assertion yang digunakan untuk mempermudah pengujian) secara manual karena terdapat beberapa pengujian unit di dalam class UTXO. Namun, masalah ini semestinya diperbaiki pada rilis berikutnya. package.json Anda untuk skrip ini seharusnya terlihat seperti berikut:
{
"name": "helius-tutorial",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"@lightprotocol/cli": "^0.1.1-alpha.21",
"@types/node": "^20.6.0",
"chai": "^4.3.8",
"typescript": "^5.2.2"
},
"dependencies": {
"@coral-xyz/anchor": "^0.28.1-beta.2",
"@lightprotocol/zk.js": "^0.3.2-alpha.14",
"@solana/web3.js": "^1.78.4"
}
}Kesimpulan
Selamat! Dalam tutorial ini, kita telah membahas seluk-beluk privasi, pentingnya privasi, dan cara bertransaksi SOL secara privat menggunakan Elusiv dan Light Protocol. Dengan Elusiv, kita mempelajari cara mengambil saldo privat, mengirim SOL secara privat, dan bahkan memfasilitasi pengisian otomatis ketika saldo privat habis atau belum tersedia. Dengan Light Protocol, kita mempelajari cara menyiapkan proses inisialisasinya yang kompleks dan sangat modular, melindungi SOL, serta mengeksekusi transfer privat.
Jadi, Anda mungkin bertanya-tanya mana yang sebaiknya digunakan? Jawabannya tergantung kebutuhan! Dengan Elusiv, kode kita berfokus pada pengisian saldo privat dari pool bersama dan pengiriman transaksi secara privat. Skrip berinteraksi dengan smart contract yang telah ditentukan dan mengelola pool Elusiv untuk mewujudkannya. Dengan Light Protocol, kita membangun proses inisialisasi yang lebih fleksibel, meskipun kompleks, untuk membuat alur kerja yang mengelola beberapa pengguna yang berinteraksi dengan program Solana penjaga privasi. Dengan Light, kita juga dapat membuat Private Solana Program (PSP) khusus sendiri jika diperlukan. Keduanya memiliki kompromi dalam aspek seperti dokumentasi dan implementasi tertentu. Namun, kedua protokol sama-sama berfokus pada privasi dan transaksi yang aman. Jika aplikasi Anda memerlukan kontrol yang lebih terperinci atas fitur privasi dan Anda ingin mengenkripsi bagian tertentu dari state aplikasi, pertimbangkan untuk menggunakan Light Protocol. Atau, jika Anda membuat sesuatu yang lebih sederhana dan ingin menambahkan lapisan privasi untuk transfer token di devnet/mainnet, Elusiv mungkin menjadi opsi yang lebih baik.
Teknik, kode, dan wawasan dalam artikel ini menawarkan titik awal yang kuat untuk membangun aplikasi berfokus pada privasi di Solana. Pentingnya privasi dalam teknologi blockchain tidak dapat dilebih-lebihkan. Seiring meningkatnya permintaan terhadap sistem terdesentralisasi, kebutuhan akan fitur pendukung privasi yang memberdayakan pengguna, melindungi hak-hak mereka, dan mewujudkan tujuan sejati teknologi blockchain generasi awal juga meningkat. Privasi itu penting, dan kini dengan Elusiv serta Light Protocol, Anda dapat menjadikan Solana blockchain yang lebih aman!
Jika Anda sudah membaca sejauh ini, anon, terima kasih!
Referensi Tambahan / Bacaan Lebih Lanjut
- Manifesto Seorang Cypherpunk
- Elusiv
- Dokumentasi Elusiv
- Elusiv SDK
- Contoh Elusiv
- Light Protocol
- zk.js
- Contoh Implementasi Private Solana Program
Artikel Terkait
Berlangganan Helius
Ikuti perkembangan terbaru dalam pengembangan Solana dan dapatkan pembaruan saat kami memublikasikan postingan


