RSA e rastësishme në blockchain

Ekziston një problem - është e vështirë të gjenerosh një numër të rastësishëm në një rrjet të decentralizuar. Pothuajse të gjithë blockchains e kanë hasur tashmë këtë. Në të vërtetë, në rrjetet ku nuk ka besim midis përdoruesve, krijimi i një numri të rastësishëm të pamohueshëm zgjidh shumë probleme.

Në këtë artikull ne ju tregojmë se si arritëm ta zgjidhim problemin duke përdorur lojërat si shembull. E para prej tyre ishte Pema e Krishtlindjeve e valëve. Për zhvillim, na duhej një gjenerues i numrave të rastësishëm.

RSA e rastësishme në blockchain

Fillimisht, ne planifikuam të gjeneronim një numër të bazuar në informacionin nga blockchain. Megjithatë, atëherë u bë e qartë: numri mund të manipulohej, që do të thotë se zgjidhja nuk është e përshtatshme.

Ne dolëm me një zgjidhje: përdorni skemën e zgjerimit të angazhimit. Serveri mori me mend një numër nga 1 në 5, shtoi një kripë në të dhe më pas hasi rezultatin duke përdorur Funksionet Keccak. Serveri vendosi kontratën inteligjente me numrin tashmë të ruajtur paraprakisht. Rezulton se loja zbret tek përdoruesi që merr me mend numrin e fshehur nga hash-i.

Lojtari vendosi një bast dhe serveri dërgoi numrin e fshehur dhe "kripën" në kontratën inteligjente. Me fjalë të thjeshta, ai zbuloi kartat. Pas kësaj, serveri kontrolloi numrat dhe vendosi nëse përdoruesi fitoi apo humbi.

Nëse serveri nuk dërgoi një numër ose "kripë" për verifikim, përdoruesi fitoi. Në këtë rast, për secilën lojë ishte e nevojshme të vendosni paraprakisht një kontratë inteligjente dhe të përfshini fitimet e mundshme në të. Doli të ishte e papërshtatshme, kërkon kohë dhe e shtrenjtë. Në atë kohë nuk kishte zgjidhje tjetër të sigurt.

Kohët e fundit, ekipi i Tradisys propozoi shtimin e një funksioni në protokollin Waves rsaVerify(). Ai kontrollon vlefshmërinë e nënshkrimit RSA bazuar në çelësin publik dhe privat. Si rezultat, funksioni u shtua.

Ne kemi zhvilluar tre lojëra: Roller zare, Coin Flip и Ride On Waves. Secili prej tyre zbaton teknologjinë e numrave të rastësishëm. Le të kuptojmë se si funksionon.

RSA e rastësishme në blockchain

Le të shohim krijimin e një numri të rastësishëm duke përdorur Ride on Waves si shembull. Kontrata e zgjuar mund të gjendet këtu.

Shko te skeda Dorëshkrim dhe zgjidhni Dekompiluar. Do të shihni kodin e kontratës inteligjente (aka script).

RSA e rastësishme në blockchain

Kodi i kontratës inteligjente përmban një sërë funksionesh. Ato të shënuara si @Callable mund të lansohen duke përdorur Transaksionet e thirrjeve. Ne jemi të interesuar për dy funksione: bast и të tërheqë:

  • bast func (playerChoice)
  • tërheqja e funksionit (Id i lojës, rsaSign)

1. Përdoruesi zgjedh gjatësinë e segmentit dhe madhësinë e bastit.

RSA e rastësishme në blockchain

2. Klienti krijon një funksion bast. Për imazhin e mësipërm do të ishte bast ("50").

3. Klienti dërgon një transaksion Invocation në adresën e kontratës inteligjente (transmetimi InvocationTx). Transaksioni përmban funksionin e bastit si parametër thirrjeje. Kjo do të thotë që transaksioni Invocation shkakton ekzekutimin e funksionit të bastit (zgjedhja: String) në kontratën inteligjente.

RSA e rastësishme në blockchain

4. Merrni parasysh funksionin e bastit:

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

Funksioni shkruan një lojë të re në gjendjen e kontratës inteligjente. Gjegjësisht:

  • Identifikues unik për një lojë të re (ID e lojës)
  • Gjendja e lojës = DORËZUAR
  • Zgjedhja e lojtarit (gjatësia e segmentit 50)
  • Çelësi publik
  • Fitimet e mundshme (në varësi të bastit të lojtarit)

RSA e rastësishme në blockchain

Kështu duket një rekord i të dhënave në blockchain (kyç-vlerë):

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

"Çelësi" (çelës) - ID e lojës lojë e re. Të dhënat e mbetura përmbahen në rreshtin e fushës "vlera". Këto shënime ruhen në skedë Data kontratë inteligjente:

RSA e rastësishme në blockchain

RSA e rastësishme në blockchain

5. Serveri “shikon” kontratën inteligjente dhe gjen transaksionin e dërguar (lojë e re) duke përdorur blockchain Api. ID-ja e lojës së lojës së re është regjistruar tashmë në blockchain, që do të thotë se nuk mund të ndryshohet ose të ndikohet më

6. Serveri gjeneron një funksion tërheqjeje (gameId, rsaSign). Për shembull, si kjo:

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

7. Serveri dërgon një transaksion Invocation në kontratën inteligjente (transmetimi InvocationTx). Transaksioni përmban një thirrje për funksionin e formuar të tërheqjes (gameId, rsaSign):

RSA e rastësishme në blockchain

Funksioni përmban ID e lojës lojë e re dhe rezultati i nënshkrimit RSA të një identifikuesi unik me një çelës privat. Rezultati i nënshkrimit është i pandryshuar.

Çfarë do të thotë kjo?

Ne marrim të njëjtën vlerë (idn e lojës) dhe aplikojmë metodën e nënshkrimit RSA për të. Ne do të marrim gjithmonë të njëjtin rezultat. Kështu funksionon algoritmi RSA. Numri përfundimtar nuk mund të manipulohet, pasi id i lojës dhe rezultati i aplikimit të RSA nuk dihen. Zgjedhja e një numri është gjithashtu e kotë.

8. Blockchain pranon transaksionin. Ai ekzekuton funksionin e tërheqjes (gameId, rsaSign)

9. Brenda funksionit të tërheqjes, ndodh tërheqja GenerateRandInt funksionet (Id i lojës, rsaSign). Ky është një gjenerues numrash të rastësishëm

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

rant - dhe ka një numër të rastësishëm.

Së pari, merret vargu, i cili është rezultat i nënshkrimit RSA ID e lojës çelës privat (rsaSign). Më pas hash me SHA-256 (sha256 (rsaSign)).

Ne nuk mund të parashikojmë rezultatin e nënshkrimit dhe hashimin pasues. Prandaj, është e pamundur të ndikohet në gjenerimin e një numri të rastësishëm. Për të marrë një numër në një interval të caktuar (për shembull, nga 1 në 100), përdorni funksionin e konvertimit toInt dhe %100 (i ngjashëm me mod).

Në fillim të artikullit përmendëm funksionin rsaVerify(), i cili ju lejon të kontrolloni vlefshmërinë e një nënshkrimi RSA me një çelës privat kundrejt atij publik. Këtu është pjesa GenerateRandInt(gameId,rsaSign):

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

Çelësi publik RSAPUBLIC dhe vargu rsaSign kalojnë në hyrje. Nënshkrimi kontrollohet për vlefshmëri. Numri gjenerohet nëse kontrolli është i suksesshëm. Përndryshe, sistemi konsideron se nënshkrimi nuk është i vlefshëm (Invalid RSA signature).

Serveri duhet të nënshkruajë ID-në e lojës me një çelës privat dhe të dërgojë një nënshkrim të vlefshëm Rsa brenda 2880 blloqeve. Parametri konfigurohet gjatë vendosjes së kontratës inteligjente. Nëse asgjë nuk ndodh brenda kohës së caktuar, përdoruesi fiton. Në këtë rast, çmimi duhet të dërgohet në adresën tuaj vetë. Rezulton se "nuk është fitimprurëse që serveri të mashtrojë", sepse kjo çon në humbje. Më poshtë është një shembull.

RSA e rastësishme në blockchain

Përdoruesi është duke luajtur Roller zare. Zgjodha 2 nga 6 anët e kubit, basti është 14 VALËT. Nëse serveri nuk dërgon një nënshkrim të vlefshëm RSA në kontratën inteligjente brenda kohës së caktuar (2880 blloqe), përdoruesi do të marrë 34.44 VALËT.

Për të gjeneruar numra në lojëra, ne përdorim një orakull - një sistem të jashtëm, jo-blockchain. Serveri kryen një nënshkrim RSA të ID-së së lojës. Kontrata e zgjuar kontrollon vlefshmërinë e nënshkrimit dhe përcakton fituesin. Nëse serveri nuk dërgon asgjë, atëherë përdoruesi fiton automatikisht.

Kjo është një metodë e ndershme gjenerimi, sepse manipulimi është teknikisht i pamundur. Të gjitha lojërat Tradisys funksionojnë bazuar në algoritmin e përshkruar. Kështu funksionojnë lojërat blockchain. Gjithçka është transparente dhe e verifikueshme. Nuk ka analoge të një sistemi të tillë në asnjë blockchain tjetër. Kjo është një rastësi e drejtë.

Burimi: www.habr.com

Shto një koment