Selamat siang, para pembaca!
Artikel ini tentang Rantai Kas Plasma dan menjelaskan topik-topik berikut:
- trilemma skalabilitas dan metode untuk solusinya;
- struktur data rantai anak dan tampilannya di rantai akar;
- implementasi input ke rantai akar;
- implementasi penarikan dari rantai root.
Opporty menggunakan bahasa pemrograman Javascript untuk mengimplementasikan rantai anak, serta Soliditas untuk rantai root. Contoh kode disediakan dalam bahasa-bahasa ini.

Blockchain dan desentralisasi memungkinkan untuk mengoptimalkan dan meningkatkan kinerja hampir semua bidang kehidupan di mana Internet dan teknologi informasi digunakan. Mereka meningkatkan keandalan, efisiensi keuangan, dan juga memfasilitasi digitalisasi barang dan barang nyata.
Kontrak pintar membawa logika bisnis ke jaringan yang didesentralisasi. Ini memungkinkan Anda untuk membangun aplikasi DAPP baru.
Pengerjaan kontrak pintar dan pengoperasian aplikasi yang cepat dengan basis data terdistribusi hanya dapat dimungkinkan jika kondisi skalabilitas terpenuhi.
Blokir modern yang terdesentralisasi memiliki beberapa kelemahan. Yang utama adalah skalabilitas. Ethereum memproses sekitar 20 tx / s. Ini tidak cukup dalam realitas keuangan modern. Pada saat yang sama, Ethereum memiliki tingkat perlindungan setinggi mungkin terhadap peretasan dan gangguan jaringan. Cryptocurrency lain dan sistem yang dibangun di blockchain tidak memiliki tingkat desentralisasi yang tinggi, yang mengurangi kepercayaan pada jaringan.
Trilemma skalabilitas
Ada trilemma skalabilitas blockchain yang mencakup tiga komponen:
- desentralisasi;
- keamanan
- skalabilitas.
Desentralisasi dalam Trilemma
Desentralisasi, seperti yang disiratkan oleh istilah tersebut, mencerminkan tingkat diversifikasi kepemilikan aktivitas dalam blockchain, serta tingkat diversifikasi pembuatan blok dan menghasilkan entri buku besar baru.
Untuk kejelasan, perlu untuk berbicara tentang organisasi yang paling tersentralisasi. Biasanya database sederhana digunakan sebagai pengganti blockchain. Organisasi semacam itu dijalankan oleh administrator khusus. Semua transaksi dapat dibatalkan dengan intervensi manual.
Dalam jaringan yang sepenuhnya terdesentralisasi, setiap pengguna dapat berpartisipasi dalam membangun jaringan.
Konsekuensi paling penting dari desentralisasi adalah bahwa sebagian besar nilai diberikan kepada komunitas yang terlibat dalam menciptakan blockchain. Tidak ada tim perantara manajer yang menerima semua manfaat alih-alih mereka yang menghasilkan struktur jaringan itu sendiri. Faktanya, sebagian besar proyek crypto sepenuhnya dimiliki oleh kontributor atau penggunanya, bukan pendiri. Ini jelas merupakan model yang lebih menarik bagi mereka yang bukan pendiri.
Keamanan di Trilemma
Ini tentang kemampuan blockchain untuk menahan serangan dari sumber eksternal dan menjaga sistem dalam keadaan tidak berubah. Sebagian besar blockchains tunduk pada banyak ancaman keamanan potensial. Sangat penting untuk mengetahui tentang vektor serangan dan opsi pertahanan yang paling umum.
Dalam hal ini, desentralisasi dan keamanan berjalan beriringan. Semakin banyak node, semakin sedikit jaringan bergantung pada sisi terpusat dan, oleh karena itu, risiko memiliki titik sentral kegagalan. Namun, ada banyak vektor serangan lain yang mengancam jaringan desentralisasi, termasuk:
>
50% serangan - objek yang memiliki lebih dari 50% dari total token yang belum dibayar sebenarnya memiliki jaringan;
>
Sybil Attack - pengguna dapat menghasilkan banyak pengidentifikasi dalam sistem untuk secara efektif mengontrol bagian yang signifikan dalam kepemilikan dan / atau pengambilan keputusan di jaringan;
>
DDoS - serangan penolakan layanan terdistribusi (DDoS) terjadi ketika ada niat untuk mengganggu lalu lintas di jaringan, mengisi jaringan dengan transaksi berbahaya;
>
Serangan kolusi - satu atau beberapa objek (atau node) memutuskan untuk bersatu untuk melakukan operasi jahat di jaringan.
Skalabilitas dalam Trilemma
Tingkat skalabilitas penting karena menentukan throughput akhir, dengan kata lain, batas atas ukuran jaringan. Pertanyaan paling penting untuk ditanyakan ketika mengevaluasi suatu jaringan adalah: "Berapa banyak pengguna yang dapat ditahan oleh sistem ini?" Bitcoin saat ini memiliki antara 2,9 dan 5,8 juta pemegang dompet. EOS memiliki beberapa ribu anggota.
Skalabilitas dan desentralisasi dapat hidup berdampingan, tetapi keamanan berkurang. Pengembang memilih platform yang paling sesuai dengan kebutuhan mereka. Pengguna melakukan hal yang sama. Pendapat kedua belah pihak terkadang berbeda. Beberapa pengguna bersedia mengorbankan keamanan untuk skalabilitas, yang lain bersedia mengorbankan skalabilitas untuk keamanan, tetapi menyeimbangkan jauh lebih sulit.
"Holy Grail" dalam teknologi blockchain
Menurut definisi, blockchain hanya memiliki dua dari tiga properti berikut:
- Desentralisasi (setiap peserta hanya memiliki akses ke sumber daya O ©, yaitu ke laptop biasa atau VPS kecil);
- Skalabilitas (kemampuan untuk memproses transaksi O (n)> O ©);
- Keamanan (perlindungan terhadap penyusup yang menggunakan sumber daya O (n)).

Hijau: Keadaan seimbang dari tiga kondisi.
Merah: keamanan kuat tetapi desentralisasi dan skalabilitas terbatas.
Biru: efisiensi tinggi, tetapi keamanan dan desentralisasi terbatas.
Hitam: desentralisasi tinggi, tetapi tidak ada aspek skalabilitas dan keamanan.
Gray: desentralisasi penuh, dengan kualitas keamanan dan skalabilitas yang minimal atau hilang.
Violet: keseimbangan yang seimbang antara keamanan dan skalabilitas, penolakan desentralisasi.
"Cawan Suci" dalam teknologi blockchain berarti menggabungkan ketiga aspek.
Dalam sebagian besar proyek saat ini bekerja dengan cryptocurrency, dua sifat dasar dicapai: desentralisasi dan keamanan. Skalabilitas menderita.
Solusi yang menjanjikan untuk trilemma
Bukti Pasak (PoS)
Proof of Stake (PoS) memberikan peningkatan skalabilitas yang potensial. POS menggantikan penambangan cryptocurrency berdasarkan sistem Proof of Work (PoW). Pilihan validator sangat cepat - dengan cara deterministik. Pada saat yang sama, tidak ada biaya energi dan ramah lingkungan.
Sidechains
Dalam jaringan virtual Ethereum, ada kemungkinan membuat jaringan samping di mana proyek dapat memproses transaksi individu dan kemudian hanya mencatat hasil awal dan akhir dalam jaringan Ethereum. Ini mengurangi beban pada EVM, tetapi memberikan lebih banyak kepercayaan dalam pengelolaan sidechain. Dengan demikian, kepercayaan pada pihak ketiga mengurangi desentralisasi.
Sharding
Sharding memecah transaksi menjadi potongan data yang lebih kecil. Alih-alih setiap node individu dalam jaringan yang memproses seluruh transaksi, node dibagi menjadi kelompok-kelompok, dan kelompok-kelompok node ini memproses potongan data tertentu. Kemudian, selama pemrosesan, potongan-potongan data ini diasimilasi ulang untuk penyimpanan permanen pada blockchain.
Tambah ukuran blok
Litecoin dan Bitcoin Cash (BCH) adalah "garpu" untuk blockchain Bitcoin. Forking pada dasarnya menyalin satu blockchain. Setelah bercabang, Anda dapat membuat perubahan. Baik LTC dan BCH meningkatkan ukuran setiap blok, yang memungkinkan untuk menyimpan lebih banyak transaksi per blok, sehingga meningkatkan kecepatan pemrosesan transaksi.
Jaringan kilat
Solusi sidechain pertama adalah kilat. Gagasan utama dari Lightning Network adalah bahwa tidak semua transaksi harus dicatat dalam blockchain, karena ini membebani jaringan. Jika pengguna mentransfer dana satu sama lain beberapa kali, maka mendaftarkan setiap transfer adalah opsional. Cukup hanya dengan membuka semacam saluran pembayaran dan menuliskan data tentang pembukaannya di blockchain. Saluran ini akan tetap terbuka sesuai kebutuhan. Ketika akan diperlukan untuk menutupnya, hasil dari semua transaksi yang dilakukan dalam saluran ini hanya ditulis ke blockchain. Mengikuti gagasan ini, Anda dapat membuat seluruh jaringan saluran untuk pembayaran. Maka transaksi pada blockchain akan lebih jarang digunakan.
Saluran pembayaran hanyalah kombinasi dari beberapa transaksi. Saluran dapat ditutup oleh salah satu anggotanya. Tindakan ini akan mirip dengan membuka brankas, yang memungkinkan Anda untuk mengambil dana milik peserta dan menuliskan data pada transfer mereka ke blockchain.
Teknologi ini menjadi sangat kuat ketika beberapa saluran tersebut digabungkan menjadi jaringan yang disebut The Lightning Network. Jaringan ini dibangun khusus untuk Bitcoin.
Raiden jaringan
Untuk Ethereum, mitra Lightning yang paling terkenal adalah Raiden Network.
Ini adalah solusi untuk penskalaan di luar blockchain utama. Ini kompatibel dengan transfer token ERC-20 di saluran pembayaran dua arah.
Arsitektur dasarnya kompleks, tetapi interaksi dengan Raiden membutuhkan pengembang untuk hanya berinteraksi dengan API untuk membuat aplikasi yang dapat diukur pada Raiden.
Raiden dirancang untuk memberikan pembayaran instan dan komisi rendah, meningkatkan kerahasiaan transaksi dan pembayaran mikro. Sebagian besar saluran pembayaran ada di luar jaringan dan hanya sesekali membentuk transaksi dalam rantai root, yang secara signifikan mengurangi throughput rantai anak.
Solusi optimal
Ideolog petir telah menciptakan konsep childchain baru yang memecahkan masalah kecepatan blockchain.
Peluang praktis mengimplementasikan konsep Plasma dan Plasma Cash.
Plasma adalah serangkaian kontrak pintar yang berjalan di atas rantai akar Ethereum dan terdiri dari jaringan rantai anak yang terhubung ke rantai akar dalam struktur pohon hierarkis.
Artinya, keamanan rootchain Ethereum digunakan untuk mengoptimalkan skalabilitas.
Uang Tunai Plasma: Opsi Opporty
Opporty menggunakan implementasi Plasma Cash dalam versi pertama.Model ini adalah implementasi plasma paling efektif dalam hal skalabilitas.
Plasma Cash adalah sistem yang didasarkan pada penggunaan pengidentifikasi unik untuk setiap token dalam rantai Plasma. Yaitu, NFT diterapkan dan token dalam jaringan menerima nomor seri unik.
Fitur Uang Tunai Plasma:
- Validasi Sharded di sisi klien - pelanggan hanya perlu memantau rantai Plasma mereka untuk mendapatkan token mereka. Ini berarti bahwa throughput transaksi dapat meningkat tanpa menambah beban pada pengguna individu.
- Penyederhanaan keluar massal - massa keluar menjadi kurang dari ancaman bagi jaringan, karena pencuri harus menyerahkan transaksi keluar untuk setiap token yang ingin dicuri.
- Kurangnya konfirmasi dua arah - transaksi tidak lagi membutuhkan pengiriman dan konfirmasi dua langkah. Sebagai gantinya, transaksi dapat dihabiskan segera setelah dimasukkan dalam rantai utama.
Kerugian:
Denominasi besar token - karena setiap token harus diberi nomor seri, Anda tidak dapat menghasilkan token kecil sewenang-wenang. Hal ini disebabkan oleh fakta bahwa pada titik tertentu nilai pembelian token akan lebih dari nilai token itu sendiri.
Struktur Transaksi dalam Uang Tunai Plasma yang Tepat
Opporty menggunakan Javascript untuk mengimplementasikan childchain. Setiap transaksi dalam Opporty Plasma Cash memiliki struktur yang serupa:
const transactionFields = [ {name: 'prevHash'}, {name: 'prevBlock', int: true, default: 0}, {name: 'tokenId', isDecimal: true}, {name: 'newOwner'}, {name: 'type'}, {name: 'signature'}, ]
Elemen utama di sini adalah tautan ke blok prevBlock sebelumnya (diperlukan untuk bergerak di sekitar rantai blok), tokenId token identifier (harus unik), serta pemilik baru pemilik terakhir token.
Selanjutnya, untuk merakit blok dan mendapatkan hash rantai root, jenis khusus pohon Patricia Merkle Trie digunakan. Pohon yang sama digunakan dalam Ethereum. Ini memiliki tampilan yang dikompresi. Pada saat yang sama, Anda masih dapat menerima bukti penyertaan atau non-penyertaan transaksi dalam suatu blok.
Tanda tangan adalah tanda tangan pada kurva elips.
Transaksi yang menghabiskan token dengan tokenId yang diberikan hanya valid jika itu termasuk dalam pohon Merkle di posisi tokenId, yaitu, untuk setiap token di pohon Merkle hanya ada satu "tempat" yang menghabiskan token ini di mana transaksi diizinkan. Format ini memungkinkan pengguna untuk memeriksa riwayat lengkap rantai Plasma, serta membuktikan dan menyangkal kepemilikan untuk token tertentu.
Untuk menghabiskan token, Anda perlu memvalidasi rantai, memeriksa blok yang hilang, dan hanya kemudian menandatangani kembali transaksi bersama dengan seluruh sejarah.
Bloknya adalah sebagai berikut:
const blockFields = [ {name: 'prevHash'}, {name: 'blockNum', isDecimal: true}, {name: 'transactions'}, {name: 'merkleRoot'}, {name: 'time'} ]
Pada tingkat dasar, blockchain hanyalah rantai blok dengan tautan ke blok sebelumnya. Struktur seperti itu memungkinkan untuk memperoleh sifat kekekalan, yaitu, tidak menulis ulang sejarah. merkleRoot memungkinkan untuk menulis pos pemeriksaan ke rantai root.
Di rantai akar, di tingkat kontrak pintar, sepertinya ini (Bahasa Soliditas):
/* * Block structure (represents one block in a chain) */ struct Block { uint block_num; bytes32 merkle_root; uint time; /* * Transaction structure (decoded from RLP form) */ struct Transaction { bytes32 prevhash; uint prev_block; uint token_id; address new_owner; }
Pengkodean dilakukan dengan menggunakan pengodean / decoding - fungsi serialisasi / deserialisasi RLP.
Cara memasukkan Uang Plasma
Siapa pun dapat menyetor dana ke dalam Plasma Cash hanya dengan mentransfer eter ke kontrak pintar. Akibatnya, token OPP akan diterima pada posisi tokenId tertentu.
Berikut ini adalah implementasi dalam Solidity:
function deposit() public payable { uint token_id = uint(keccak256(msg.sender, msg.value, deposit_blk)); // token.index = deposit_blk; tokens[token_id] = msg.value; deposit_blk += 1; emit DepositAdded(msg.sender, msg.value, token_id, current_blk); }
Yaitu, tokenId dihasilkan sebagai angka acak (hash). Selanjutnya, suatu peristiwa dihasilkan yang dipindai dalam rantai anak.
Cara-cara menarik ke Tunai Plasma
Setiap orang dapat menarik tokennya dengan memberikan dua transaksi terakhir dalam riwayat kepemilikan token.
Implementasi keluar dari rantai root:
function startExit(uint block_num, bytes tx1, bytes tx0, bytes proof1, bytes proof0) public returns (uint exit_id) { require(checkPatriciaProof(keccak256(tx1), childChain[block_num].merkle_root, proof1)); bytes32 prev_hash; uint prev_blk; uint token_id; address new_owner; (prev_hash, prev_blk, token_id, new_owner,) = getTransactionFromRLP(tx1); require(msg.sender == new_owner); require(tokens[token_id] > 0); bytes32 hashPrevTx = keccak256(tx0); require(checkPatriciaProof(hashPrevTx, childChain[prev_blk].merkle_root, proof0)); require(prev_hash == hashPrevTx); Exit storage record = exitRecords[token_id]; require(record.block_num == 0); record.block_num = block_num; record.new_owner = msg.sender; record.prev_block = prev_blk; if (childChain[block_num].time > block.timestamp - week) record.priority = childChain[block_num].time; else record.priority = block.timestamp - week; exits.add(record.priority); exit_ids[record.priority].push(token_id); emit ExitAdded(msg.sender, record.priority, token_id); return token_id; }
Pertama, dua transaksi diperiksa. Jika pengguna saat ini adalah pemilik transaksi, maka kami cukup menambahkan outputnya ke struktur dan biarkan dua minggu untuk kesempatan untuk menantang output.
Kesimpulannya dapat ditantang dalam tiga cara:
- Memberikan konfirmasi pengeluaran untuk transaksi:
function challengeSpent(uint exit_id, uint blk_num, bytes tx1, bytes proof) public { require(checkPatriciaProof(keccak256(tx1), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); uint prev_block; uint token_id; (, prev_block , token_id, ) = getTransactionFromRLP(tx1); require(tokens[token_id] > 0); require(prev_block == record.block_num && record.block_num < blk_num); require(token_id == exit_id); exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); }
Jika ada transaksi yang sudah menghabiskan token yang ditampilkan, maka penarikan seperti itu akan dibatalkan!
- Bukti pengeluaran untuk transaksi sebelumnya:
/* * Challenge exit by providing * a proof of a transaction spending P(C) that appears before C */ function challengeDoubleSpend(uint exit_id, uint blk_num, bytes tx1, bytes proof) public { require(checkPatriciaProof(keccak256(tx1), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); // bytes32 prev_hash; uint prev_block; uint token_id; (, prev_block , token_id, ) = getTransactionFromRLP(tx1); require(tokens[token_id] > 0); // check if token double spent require(prev_block == record.prev_block && blk_num < record.block_num); // require(token_id == exit_id); exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); }
Ini adalah cek yang sama seolah-olah token telah dihabiskan sebelum penarikan. Pertama, periksa transaksi di root hash. Selanjutnya, kami menghapus output jika sudah digunakan.
- memberikan transaksi dalam riwayat transaksi token sebelumnya.
Ini mungkin cerita yang salah, jadi Anda perlu mengonfirmasi dengan transaksi anak:
// */ function challengeInvalidHistory(uint exit_id, uint blk_num, bytes tx0, bytes proof) public { // check if proof is valid require(checkPatriciaProof(keccak256(tx0), childChain[blk_num].merkle_root, proof)); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); bytes32 prev_hash; uint token_id; (prev_hash, , token_id, ) = getTransactionFromRLP(tx0); //require(exit_id == token_id); require(tokens[token_id] > 0); // transaction should be before exit tx in history require(blk_num < record.block_num - 1); challenged[exit_id] = blk_num; emit ChallengedInvalidHistory(exit_id, token_id); }
Memanggil skrip pertama dan kedua segera memblokir output.
Panggilan ke skenario ketiga dapat dijawab dengan memberikan keturunan langsung. Itu harus sama dengan atau di depan transaksi induk.
/* * Respond to invalid history challenge by providing * the direct child of C*, which must be either equal to or before P( C ) */ function respondChallenge(uint exit_id, uint blk_num, bytes childtx, bytes proof) public { require(challenged[exit_id] > 0); Exit memory record = exitRecords[exit_id]; require(record.block_num > 0); require(checkPatriciaProof(keccak256(childtx), childChain[blk_num].merkle_root, proof)); // get transaction from rlpencoded form bytes32 prev_hash; uint prev_block; uint token_id; (prev_hash, prev_block, token_id, ) = getTransactionFromRLP(childtx); // if direct child if (prev_block == challenged[exit_id] ) { if (blk_num <= record.prev_block && token_id == exit_id ) { delete challenged[exit_id]; emit ExitRespondedEvent(exit_id); } else { exit_ids[record.priority].remove(exit_id); delete exitRecords[exit_id]; emit ExitChallengedEvent(exit_id); } } }
Yaitu, jika transaksi anak yang benar diterima, hasilnya disengketakan dan tetap dalam antrian!
Setelah membangun bagian dari protokol Plasma Tunai yang Tepat, kesimpulan berikut dibuat:
Protokol ini memberikan keamanan melalui rantai root Ethereum.
Dengan menyulitkan prosedur input dan output dari rantai root dan kompresi keadaan (blok transaksi), kami memeriksa semua metode output dan input ke rantai root, dan juga menyelidiki struktur data dasar: transaksi dan blok.
Menggunakan sidechain berdasarkan jaringan Ethereum, Anda dapat secara signifikan mempercepat transaksi. Peluang menerima hingga
300.000 transaksi per detik pada satu operator. Ini lebih dari apa yang dapat diberikan oleh sistem pembayaran saat ini.
Terlepas dari beberapa masalah ketersediaan data, operator memberikan tingkat stabilitas tinggi dari blockchain dan memungkinkan untuk melakukan transaksi bisnis internasional yang efektif.
Plasma Cash membawa peningkatan skalabilitas yang sangat besar. Oleh karena itu, Opporty menggunakan Plasma sebagai bagian dari protokol PoE-nya.
Tautan yang bermanfaat
- Plasma kertas putih
- Git hub
- Gunakan case dan deskripsi arsitektur
- Kertas jaringan petir