RSA juhuslik plokiahelas

Tekib probleem – detsentraliseeritud võrgus on keeruline juhuslikku arvu genereerida. Peaaegu kõik plokiahelad on sellega juba kokku puutunud. Tõepoolest, võrkudes, kus kasutajate vahel puudub usaldus, lahendab vaieldamatu juhusliku arvu loomine palju probleeme.

Selles artiklis räägime teile, kuidas meil õnnestus probleem mängude näitel lahendada. Esimene neist oli Waves jõulupuu. Arenduseks vajasime juhuslike arvude generaatorit.

RSA juhuslik plokiahelas

Esialgu plaanisime genereerida numbri plokiahela info põhjal. Siis aga selgus: numbriga saab manipuleerida, mis tähendab, et lahendus ei sobi.

Leidsime lahenduse: kasutage skeemi commit-expand. Server arvas ära arvu vahemikus 1 kuni 5, lisas sellele soola ja seejärel räsis tulemuse kasutades Keccaki funktsioonid. Server juurutas nutilepingu juba salvestatud numbriga eelnevalt. Selgub, et mäng taandub sellele, et kasutaja arvab ära räsi peidetud numbri.

Mängija tegi panuse ning server saatis nutilepingusse peidetud numbri ja “soola”. Lihtsamalt öeldes paljastas ta kaardid. Pärast seda kontrollis server numbreid ja otsustas, kas kasutaja võitis või kaotas.

Kui server ei saatnud kontrollimiseks numbrit või "soola", võitis kasutaja. Sel juhul oli iga mängu jaoks vaja eelnevalt juurutada nutikas leping ja lisada sellesse potentsiaalsed võidud. See osutus ebamugavaks, aeganõudvaks ja kulukaks. Sel ajal polnud muud ohutut lahendust.

Hiljuti tegi Tradisyse meeskond ettepaneku lisada Waves'i protokolli funktsioon rsaVerify(). See kontrollib avaliku ja privaatvõtme alusel RSA allkirja kehtivust. Selle tulemusena lisati funktsioon.

Oleme välja töötanud kolm mängu: Täringurull, Coin Flip и Ride On Waves. Igaüks neist rakendab juhuslike arvude tehnoloogiat. Mõelgem välja, kuidas see toimib.

RSA juhuslik plokiahelas

Vaatame juhusliku arvu genereerimist, kasutades näitena Ride on Waves. Tark leping on leitav siin.

Minge vahekaardile Script ja valige Dekompileeritud. Näete nutika lepingu koodi (teise nimega skript).

RSA juhuslik plokiahelas

Nutika lepingu kood sisaldab funktsioonide komplekti. Neid, mis on märgitud kui @Callable, saab käivitada kasutades Väljakutsete tehingud. Oleme huvitatud kahest funktsioonist: panus и tagasi võtma:

  • func bet (mängija valik)
  • func return(gameId,rsaSign)

1. Kasutaja valib segmendi pikkuse ja panuse suuruse.

RSA juhuslik plokiahelas

2. Klient loob panuse funktsiooni. Ülaltoodud pildi puhul oleks see nii panus ("50").

3. Klient saadab Invocation tehingu targa lepingu aadressile (edastus InvocationTx). Tehing sisaldab kõneparameetrina panuse funktsiooni. See tähendab, et väljakutsetehing käivitab nutika lepingu panusfunktsiooni (valik: String) täitmise.

RSA juhuslik plokiahelas

4. Mõelge panuse funktsioonile:

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

Funktsioon kirjutab nutika lepingu olekusse uue mängu. Nimelt:

  • Uue mängu kordumatu identifikaator (mängu ID)
  • Mängu olek = ESITATUD
  • Mängija valik (segmendi pikkus 50)
  • Avalik võti
  • Potentsiaalsed võidud (olenevalt mängija panusest)

RSA juhuslik plokiahelas

Selline näeb välja andmekirje plokiahelas (võtmeväärtus):

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

"Võti" (võti) – mängu id uus mäng. Ülejäänud andmed sisalduvad välja "väärtus" real. Need kirjed salvestatakse vahekaardile kuupäev tark leping:

RSA juhuslik plokiahelas

RSA juhuslik plokiahelas

5. Server “vaatab” nutikat lepingut ja leiab saadetud tehingu (uue mängu) plokiahela Api abil. Uue mängu mängu ID on juba plokiahelas salvestatud, mis tähendab, et seda ei saa enam muuta ega mõjutada

6. Server genereerib väljavõtmise funktsiooni (gameId, rsaSign). Näiteks nii:

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

7. Server saadab nutikale lepingule väljakutsetehingu (edastus InvocationTx). Tehing sisaldab väljakutset moodustatud tagasivõtmise funktsioonile (gameId, rsaSign):

RSA juhuslik plokiahelas

Funktsioon sisaldab mängu id uus mäng ja privaatvõtmega kordumatu identifikaatori RSA allkirjastamise tulemus. Allkirja tulemus on muutumatu.

Mida see tähendab?

Võtame sama väärtuse (mängu ID) ja rakendame sellele RSA allkirjameetodit. Saame alati sama tulemuse. Nii töötab RSA algoritm. Lõpliku numbriga ei saa manipuleerida, kuna mängu ID ja RSA rakendamise tulemus pole teada. Numbri valimine on samuti mõttetu.

8. Blockchain aktsepteerib tehingut. See käivitab väljavõtmise funktsiooni (gameId, rsaSign)

9. Väljatõmbamisfunktsiooni sees toimub väljatõmbamine GenerateRandInt funktsioonid (gameId, rsaSign). See on juhuslike arvude generaator

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

rand - ja seal on juhuslik arv.

Esiteks võetakse string, mis on RSA allkirja tulemus mängu id privaatvõti (rsaSign). Seejärel räsitakse SHA-256-ga (sha256 (rsaSign)).

Me ei saa ennustada allkirja ja sellele järgneva räsimise tulemust. Seetõttu on juhusliku arvu genereerimist võimatu mõjutada. Teatud vahemikus (näiteks 1 kuni 100) oleva arvu saamiseks kasutage teisendusfunktsiooni toInt ja %100 (sarnaselt mod).

Artikli alguses mainisime funktsiooni rsaVerify(), mis võimaldab privaatvõtme abil kontrollida RSA allkirja kehtivust avaliku allkirja vastu. Siin on GenerateRandInt(gameId,rsaSign) osa:

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

Avalik võti RSAPUBLIC ja rsaSign string edastatakse sisendisse. Allkirja kehtivust kontrollitakse. Kui kontroll õnnestub, genereeritakse number. Vastasel juhul leiab süsteem, et allkiri ei ole kehtiv (Invalid RSA signature).

Server peab allkirjastama mängu ID privaatvõtmega ja saatma kehtiva Rsa-allkirja 2880 ploki piires. Parameeter konfigureeritakse nutika lepingu juurutamisel. Kui määratud aja jooksul midagi ei juhtu, võidab kasutaja. Sel juhul tuleb auhind saata teie aadressile ise. Selgub, et "serveril pole petmine kasumlik", kuna see toob kaasa kahju. Allpool on näide.

RSA juhuslik plokiahelas

Kasutaja mängib Täringurull. Valisin kuubi kuuest küljest 2, panus on 6 LAINET. Kui server määratud aja jooksul (14 plokki) nutilepingule kehtivat RSA allkirja ei saada, võtab kasutaja 2880 LAINET.

Mängudes numbrite genereerimiseks kasutame oraaklit – välist, plokiahelata süsteemi. Server teostab mängu ID RSA-allkirja. Nutikas leping kontrollib allkirja kehtivust ja selgitab välja võitja. Kui server midagi ei saada, võidab kasutaja automaatselt.

See on aus genereerimismeetod, sest manipuleerimine on tehniliselt võimatu. Kõik Tradisyse mängud töötavad kirjeldatud algoritmi alusel. Nii toimivad plokiahela mängud. Kõik on läbipaistev ja kontrollitav. Sellise süsteemi analooge pole üheski teises plokiahelas. See on õiglane juhuslik.

Allikas: www.habr.com

Lisa kommentaar