Ada masalah - sulit untuk menghasilkan nomor acak dalam jaringan terdesentralisasi. Hampir semua blockchain pernah mengalami hal ini. Memang benar, dalam jaringan di mana tidak ada kepercayaan antar pengguna, pembuatan nomor acak yang tidak dapat disangkal memecahkan banyak masalah.
Pada artikel ini kami akan memberi tahu Anda bagaimana kami berhasil memecahkan masalah menggunakan game sebagai contoh. Yang pertama adalah
Awalnya, kami berencana membuat nomor berdasarkan informasi dari blockchain. Namun, kemudian menjadi jelas: angka tersebut dapat dimanipulasi, yang berarti solusinya tidak tepat.
Kami menemukan solusinya: gunakan skema commit-expand. Server menebak angka dari 1 hingga 5, menambahkan garam ke dalamnya, dan kemudian meng-hash hasilnya menggunakan
Pemain memasang taruhan, dan server mengirimkan nomor tersembunyi dan βgaramβ ke kontrak pintar. Secara sederhana, dia mengungkapkan kartunya. Setelah itu, server memeriksa nomor tersebut dan memutuskan apakah pengguna menang atau kalah.
Jika server tidak mengirimkan nomor atau βgaramβ untuk verifikasi, pengguna menang. Dalam hal ini, untuk setiap permainan, perlu menerapkan kontrak pintar terlebih dahulu dan memasukkan potensi kemenangan di dalamnya. Ternyata merepotkan, memakan waktu, dan mahal. Pada saat itu tidak ada solusi aman lainnya.
Baru-baru ini, tim Tradisys mengusulkan penambahan fungsi ke protokol Waves rsaVerifikasi(). Ia memeriksa validitas tanda tangan RSA berdasarkan kunci publik dan pribadi. Hasilnya, fitur tersebut ditambahkan.
Kami telah mengembangkan tiga game:
Mari kita lihat menghasilkan angka acak menggunakan Ride on Waves sebagai contoh. Kontrak pintar dapat ditemukan
Buka tab Naskah dan pilih Didekompilasi. Anda akan melihat kode kontrak pintar (alias skrip).
Kode kontrak pintar berisi serangkaian fungsi. Yang ditandai sebagai @Callable dapat diluncurkan menggunakan Transaksi pemanggilan. Kami tertarik pada dua fungsi: bertaruh ΠΈ menarik:
- taruhan fungsi (Pilihan pemain)
- fungsi penarikan(gameId,rsaSign)
1. Pengguna memilih panjang segmen dan ukuran taruhan.
2. Klien membuat fungsi taruhan. Untuk gambar di atas itu adalah taruhan("50").
3. Klien mengirimkan transaksi Invokasi ke alamat kontrak pintar (broadcast InvocationTx). Transaksi tersebut berisi fungsi taruhan sebagai parameter panggilan. Artinya transaksi Invocation memicu eksekusi fungsi taruhan (pilihan: String) pada kontrak pintar.
4. Pertimbangkan fungsi taruhan:
@Callable(i)
func bet (playerChoice) = {
let newGameNum = IncrementGameNum()
let gameId = toBase58String(i.transactionId)
let pmt = extract(i.payment)
let betNotInWaves = isDefined(pmt.assetId)
let feeNotInWaves = isDefined(pmt.assetId)
let winAmt = ValidateBetAndDefineWinAmt(pmt.amount, playerChoice)
let txIdUsed = isDefined(getString(this, gameId))
if (betNotInWaves)
then throw ("Bet amount must be in Waves")
else if (feeNotInWaves)
then throw ("Transaction's fee must be in Waves")
else if (txIdUsed)
then throw ("Passed txId had been used before. Game aborted.")
else {
let playerPubKey58 = toBase58String(i.callerPublicKey)
let gameDataStr = FormatGameDataStr(STATESUBMITTED, playerChoice, playerPubKey58, height, winAmt, "")
ScriptResult(WriteSet(cons(DataEntry(RESERVATIONKEY, ValidateAndIncreaseReservedAmt(winAmt)), cons(DataEntry(GAMESCOUNTERKEY, newGameNum), cons(DataEntry(gameId, gameDataStr), nil)))), TransferSet(cons(ScriptTransfer(SERVER, COMMISSION, unit), nil)))
}
}
Fungsi ini menulis permainan baru ke dalam status kontrak pintar. Yaitu:
- Pengidentifikasi unik untuk game baru (id permainan)
- Status permainan = DIKIRIM
- Pilihan pemain (panjang segmen 50)
- Kunci publik
- Potensi kemenangan (tergantung taruhan pemain)
Seperti inilah rekaman data di blockchain (nilai kunci):
{
"type": "string",
"value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229",
"key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx"
}
"Kunci" (kunci) β ID permainan permainan baru. Data yang tersisa terdapat di baris bidang "nilai". Entri ini disimpan di tab Data kontrak pintar:
5. Server βmelihatβ kontrak pintar dan menemukan transaksi terkirim (permainan baru) menggunakan blockchain Api. ID Game dari game baru sudah tercatat di blockchain, yang berarti tidak dapat diubah atau dipengaruhi lagi
6. Server menghasilkan fungsi penarikan (gameId, rsaSign). Misalnya seperti ini:
withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==")
7. Server mengirimkan transaksi Invokasi ke kontrak pintar (broadcast InvocationTx). Transaksi tersebut berisi panggilan ke fungsi penarikan yang dibentuk (gameId, rsaSign):
Fungsinya berisi ID permainan permainan baru dan hasil penandatanganan RSA dari pengidentifikasi unik dengan kunci pribadi. Hasil tanda tangan tidak berubah.
Apa artinya ini?
Kami mengambil nilai yang sama (id game) dan menerapkan metode tanda tangan RSA padanya. Kami akan selalu mendapatkan hasil yang sama. Beginilah cara kerja algoritma RSA. Angka akhir tidak dapat dimanipulasi karena id permainan dan hasil penerapan RSA tidak diketahui. Memilih nomor juga tidak ada gunanya.
8. Blockchain menerima transaksi tersebut. Ini menjalankan fungsi penarikan (gameId, rsaSign)
9. Di dalam fungsi penarikan, penarikan terjadi Hasilkan fungsi RandInt (gameId, rsaSign). Ini adalah generator nomor acak
# @return 1 ... 100
func GenerateRandInt (gameId,rsaSign) = {
# verify RSA signature to proof random
let rsaSigValid = rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
if (rsaSigValid)
then {
let rand = (toInt(sha256(rsaSign)) % 100)
if ((0 > rand))
then ((-1 * rand) + 1)
else (rand + 1)
}
else throw ("Invalid RSA signature")
}
baris - dan ada nomor acak.
Pertama, diambil string yang merupakan hasil tanda tangan RSA ID permainan kunci pribadi (rsaTanda). Kemudian di-hash dengan SHA-256 (sha256(rsaTanda)).
Kami tidak dapat memprediksi hasil tanda tangan dan hashing selanjutnya. Oleh karena itu, tidak mungkin mempengaruhi pembentukan bilangan acak. Untuk mendapatkan angka dalam rentang tertentu (misalnya, dari 1 hingga 100), gunakan fungsi konversi toInt dan %100 (mirip dengan
Di awal artikel kami telah menyebutkan fungsinya rsaVerifikasi(), yang memungkinkan Anda memeriksa validitas tanda tangan RSA dengan kunci pribadi terhadap kunci publik. Berikut adalah bagian GenerateRandInt(gameId,rsaSign):
rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
Kunci publik RSAPUBLIC dan string rsaSign diteruskan ke input. Tanda tangan diperiksa keabsahannya. Nomor tersebut dihasilkan jika pemeriksaan berhasil. Jika tidak, sistem menganggap tanda tangan tersebut tidak valid (tanda tangan RSA tidak valid).
Server harus menandatangani id game dengan kunci pribadi dan mengirimkan tanda tangan Rsa yang valid dalam 2880 blok. Parameter dikonfigurasikan saat menerapkan kontrak pintar. Jika tidak ada yang terjadi dalam waktu yang ditentukan, pengguna menang. Dalam hal ini, hadiah harus dikirim sendiri ke alamat Anda. Ternyata βtidak menguntungkan server untuk melakukan cheatβ, karena berujung pada kerugian. Di bawah ini adalah contohnya.
Pengguna sedang bermain
Untuk menghasilkan angka dalam game, kami menggunakan oracle - sistem eksternal non-blockchain. Server melakukan tanda tangan RSA dari id game. Kontrak pintar memeriksa validitas tanda tangan dan menentukan pemenangnya. Jika server tidak mengirimkan apa pun, maka pengguna otomatis menang.
Ini adalah metode pembangkitan yang jujur, karena manipulasi secara teknis tidak mungkin dilakukan. Semua game Tradisys bekerja berdasarkan algoritma yang dijelaskan. Beginilah cara kerja game blockchain. Semuanya transparan dan dapat diverifikasi. Tidak ada analog dari sistem seperti itu di blockchain lainnya. Ini cukup acak.
Sumber: www.habr.com