RSA izlases veidā blokķēdē

Ir problēma ā€“ decentralizētā tÄ«klā ir grÅ«ti Ä£enerēt nejauÅ”u skaitli. GandrÄ«z visas blokķēdes jau ir ar to saskāruŔās. PatieŔām, tÄ«klos, kur starp lietotājiem nav uzticÄ«bas, nenoliedzama nejauÅ”a skaitļa izveidoÅ”ana atrisina daudzas problēmas.

Å ajā rakstā mēs jums pastāstÄ«sim, kā mums izdevās atrisināt problēmu, izmantojot spēles kā piemēru. Pirmais no tiem bija Viļņi Ziemassvētku eglÄ«te. Izstrādei mums bija nepiecieÅ”ams nejauÅ”o skaitļu Ä£enerators.

RSA izlases veidā blokķēdē

Sākotnēji mēs plānojām ģenerēt numuru, pamatojoties uz informāciju no blokķēdes. Tomēr tad kļuva skaidrs: ar numuru var manipulēt, kas nozīmē, ka risinājums nav piemērots.

Mēs izdomājām risinājumu: izmantojiet commit-expand shēmu. Serveris uzminēja skaitli no 1 lÄ«dz 5, pievienoja tam sāli un pēc tam sajauca rezultātu, izmantojot Keccak funkcijas. Serveris jau iepriekÅ” izvietoja viedo lÄ«gumu ar jau saglabāto numuru. Izrādās, ka spēle beidzas ar to, ka lietotājs uzmin ciparu, ko slēpj hash.

Spēlētājs izdarÄ«ja likmi, un serveris nosÅ«tÄ«ja slēpto numuru un ā€œsāliā€ viedajam lÄ«gumam. VienkārÅ”i sakot, viņŔ atklāja kārtis. Pēc tam serveris pārbaudÄ«ja skaitļus un nolēma, vai lietotājs uzvarēja vai zaudēja.

Ja serveris verifikācijai nenosÅ«tÄ«ja numuru vai ā€œsāliā€, lietotājs uzvarēja. Å ajā gadÄ«jumā katrai spēlei bija nepiecieÅ”ams iepriekÅ” izveidot viedo lÄ«gumu un iekļaut tajā iespējamos laimestus. Tas izrādÄ«jās neērti, laikietilpÄ«gi un dārgi. Toreiz cita droÅ”a risinājuma nebija.

Nesen Tradisys komanda ierosināja pievienot funkciju Waves protokolam rsaVerify(). Tā pārbauda RSA paraksta derīgumu, pamatojoties uz publisko un privāto atslēgu. Rezultātā funkcija tika pievienota.

Mēs esam izstrādājuÅ”i trÄ«s spēles: Kauliņu veltnis, Coin Flip Šø Ride On Waves. Katrs no tiem ievieÅ” nejauÅ”u skaitļu tehnoloÄ£iju. Izdomāsim, kā tas darbojas.

RSA izlases veidā blokķēdē

ApskatÄ«sim nejauÅ”a skaitļa Ä£enerÄ“Å”anu, kā piemēru izmantojot Ride on Waves. Viedo lÄ«gumu var atrast Å”eit.

Atveriet cilni Scenārijs un izvēlieties Dekompilēts. Jūs redzēsit viedā līguma kodu (aka skriptu).

RSA izlases veidā blokķēdē

Viedā lÄ«guma kods satur funkciju kopu. Tos, kas atzÄ«mēti kā @Callable, var palaist, izmantojot Izsaukuma darÄ«jumi. MÅ«s interesē divas funkcijas: derēt Šø atsaukt:

  • Func likme (spēlētāja izvēle)
  • funkcija atsaukt(gameId,rsaSign)

1. Lietotājs izvēlas segmenta garumu un likmes lielumu.

RSA izlases veidā blokķēdē

2. Klients izveido likmes funkciju. IepriekÅ” redzamajam attēlam tas bÅ«tu likme ("50").

3. Klients nosÅ«ta Invocation transakciju uz viedā lÄ«guma adresi (broadcast InvocationTx). DarÄ«jums satur likmes funkciju kā izsaukuma parametru. Tas nozÄ«mē, ka izsaukÅ”anas darÄ«jums aktivizē likmes funkcijas (izvēle: virkne) izpildi viedajā lÄ«gumā.

RSA izlases veidā blokķēdē

4. Apsveriet likmes funkciju:

@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)))
                    }
    }

Funkcija ieraksta jaunu spēli viedā līguma stāvoklī. Proti:

  • Unikāls identifikators jaunai spēlei (spēles ID)
  • Spēles stāvoklis = IESNIEGTS
  • Spēlētāja izvēle (segmenta garums 50)
  • Publiskā atslēga
  • Potenciālie laimesti (atkarÄ«bā no spēlētāja likmes)

RSA izlases veidā blokķēdē

Šādi izskatās datu ieraksts blokķēdē (atslēgas vērtība):

{
    "type": "string",
    "value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229",
    "key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx"
  }

"Atslēga" (atslēga) - spēles id jauna spēle. Pārējie dati ir ietverti lauka ā€œvērtÄ«baā€ rindā. Å ie ieraksti tiek saglabāti cilnē Datums viedais lÄ«gums:

RSA izlases veidā blokķēdē

RSA izlases veidā blokķēdē

5. Serveris ā€œapskatāsā€ viedo lÄ«gumu un, izmantojot blokķēdes Api, atrod nosÅ«tÄ«to transakciju (jaunu spēli). Jaunās spēles spēles ID jau ir ierakstÄ«ts blokķēdē, kas nozÄ«mē, ka to vairs nevar mainÄ«t vai ietekmēt

6. Serveris Ä£enerē atsaukÅ”anas funkciju (gameId, rsaSign). Piemēram, Ŕādi:

withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==")

7. Serveris nosÅ«ta Invocation transakciju viedajam lÄ«gumam (broadcast InvocationTx). DarÄ«jums satur izsaukumu uz izveidoto izņemÅ”anas funkciju (gameId, rsaSign):

RSA izlases veidā blokķēdē

Funkcija satur spēles id jauna spēle un RSA unikālā identifikatora parakstÄ«Å”anas rezultāts ar privāto atslēgu. Paraksta rezultāts ir nemainÄ«gs.

Ko tas nozīmē?

Mēs ņemam to paÅ”u vērtÄ«bu (spēles ID) un piemērojam tai RSA paraksta metodi. Mēs vienmēr iegÅ«sim to paÅ”u rezultātu. Šādi darbojas RSA algoritms. Ar galÄ«go numuru nevar manipulēt, jo spēles ID un RSA piemēroÅ”anas rezultāts nav zināms. ArÄ« skaitļa izvēle ir bezjēdzÄ«ga.

8. Blockchain pieņem darÄ«jumu. Tas palaiž izņemÅ”anas funkciju (gameId, rsaSign)

9. IzņemÅ”anas funkcijas ietvaros notiek izņemÅ”ana GenerateRandInt funkcijas (gameId, rsaSign). Å is ir nejauÅ”o skaitļu Ä£enerators

# @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")
    }

rinda - un ir nejauŔs skaitlis.

Pirmkārt, tiek ņemta virkne, kas ir RSA paraksta rezultāts spēles id privātā atslēga (rsaSign). Pēc tam jaukta ar SHA-256 (sha256 (rsaSign)).

Mēs nevaram paredzēt parakstÄ«Å”anas un turpmākās jaukÅ”anas iznākumu. Tāpēc nav iespējams ietekmēt nejauÅ”a skaitļa Ä£enerÄ“Å”anu. Lai iegÅ«tu skaitli noteiktā diapazonā (piemēram, no 1 lÄ«dz 100), izmantojiet konvertÄ“Å”anas funkciju toInt un %100 (lÄ«dzÄ«gi kā mod).

Raksta sākumā mēs minējām funkciju rsaVerify(), kas ļauj pārbaudīt RSA paraksta derīgumu, izmantojot privāto atslēgu, salīdzinot ar publisko atslēgu. Šeit ir daļa GenerateRandInt(gameId,rsaSign):

rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)

Publiskā atslēga RSAPUBLIC un rsaSign virkne tiek nodota ievadei. Tiek pārbaudīts paraksta derīgums. Numurs tiek ģenerēts, ja pārbaude ir veiksmīga. Pretējā gadījumā sistēma uzskata, ka paraksts nav derīgs (Nederīgs RSA paraksts).

Serverim jāparaksta spēles ID ar privāto atslēgu un jānosÅ«ta derÄ«gs Rsa paraksts 2880 bloku robežās. Parametrs tiek konfigurēts, izvietojot viedo lÄ«gumu. Ja nekas nenotiek atvēlētajā laikā, lietotājs uzvar. Å ajā gadÄ«jumā balva paÅ”am jānosÅ«ta uz savu adresi. Izrādās, ka ā€œserverim nav izdevÄ«gi krāptiesā€, jo tas noved pie zaudējumiem. Zemāk ir piemērs.

RSA izlases veidā blokķēdē

Lietotājs spēlē Kauliņu veltnis. Es izvēlējos 2 no 6 kuba malām, likme ir 14 VIĻŅI. Ja serveris noteiktajā laikā (2880 bloki) nenosūtīs derīgu RSA parakstu viedajam līgumam, lietotājs ņems 34.44 VIĻŅUS.

Lai ģenerētu skaitļus spēlēs, mēs izmantojam orākulu - ārēju, bez blokķēdes sistēmu. Serveris veic spēles ID RSA parakstu. Viedais līgums pārbauda paraksta derīgumu un nosaka uzvarētāju. Ja serveris neko nesūta, lietotājs automātiski uzvar.

Tā ir godÄ«ga Ä£enerÄ“Å”anas metode, jo manipulācija tehniski nav iespējama. Visas Tradisys spēles darbojas, pamatojoties uz aprakstÄ«to algoritmu. Šādi darbojas blokķēdes spēles. Viss ir caurspÄ«dÄ«gs un pārbaudāms. Šādai sistēmai nav analogu nevienā citā blokķēdē. Å Ä« ir godÄ«ga nejauŔība.

Avots: www.habr.com

Pievieno komentāru