RSA tilfeldig på blockchain

Det er et problem - det er vanskelig å generere et tilfeldig tall i et desentralisert nettverk. Nesten alle blokkjeder har allerede støtt på dette. Faktisk, i nettverk der det ikke er tillit mellom brukere, løser det å lage et ubestridelig tilfeldig tall mange problemer.

I denne artikkelen forteller vi deg hvordan vi klarte å løse problemet ved å bruke spill som eksempel. Den første av dem var Bølger juletre. For utvikling trengte vi en tilfeldig tallgenerator.

RSA tilfeldig på blockchain

I utgangspunktet planla vi å generere et tall basert på informasjon fra blokkjeden. Men da ble det klart: tallet kunne manipuleres, noe som betyr at løsningen ikke er egnet.

Vi kom opp med en løsning: bruk commit-expand-ordningen. Serveren gjettet et tall fra 1 til 5, la til et salt og hashade deretter resultatet ved hjelp av Keccak funksjoner. Serveren implementerte den smarte kontrakten med det allerede lagrede nummeret på forhånd. Det viser seg at spillet koker ned til at brukeren gjetter tallet som er skjult av hashen.

Spilleren satte en innsats, og serveren sendte det skjulte nummeret og "saltet" til smartkontrakten. Enkelt sagt avslørte han kortene. Etter det sjekket serveren tallene og bestemte om brukeren vant eller tapte.

Hvis serveren ikke sendte et nummer eller "salt" for verifisering, vant brukeren. I dette tilfellet, for hvert spill var det nødvendig å distribuere en smart kontrakt på forhånd og inkludere potensielle gevinster i den. Det viste seg å være upraktisk, tidkrevende og dyrt. På den tiden var det ingen annen sikker løsning.

Nylig foreslo Tradisys-teamet å legge til en funksjon i Waves-protokollen rsaVerify(). Den sjekker gyldigheten til RSA-signaturen basert på den offentlige og private nøkkelen. Som et resultat ble funksjonen lagt til.

Vi har utviklet tre spill: Sier Roller, Coin Flip и Ride På Bølger. Hver og en implementerer tilfeldig tallteknologi. La oss finne ut hvordan det fungerer.

RSA tilfeldig på blockchain

La oss se på å generere et tilfeldig tall ved å bruke Ride on Waves som et eksempel. Den smarte kontrakten kan bli funnet her.

Gå til fanen Script og velg Dekompilert. Du vil se den smarte kontraktskoden (alias script).

RSA tilfeldig på blockchain

Den smarte kontraktskoden inneholder et sett med funksjoner. De som er merket som @Callable kan startes ved hjelp av Invokasjonstransaksjoner. Vi er interessert i to funksjoner: satse и trekke seg:

  • func bet (spillervalg)
  • func withdraw(gameId,rsaSign)

1. Brukeren velger lengden på segmentet og innsatsstørrelsen.

RSA tilfeldig på blockchain

2. Klienten oppretter en innsatsfunksjon. For bildet over ville det vært det bet("50").

3. Klienten sender en Invocation-transaksjon til smartkontraktadressen (broadcast InvocationTx). Transaksjonen inneholder innsatsfunksjonen som en call-parameter. Dette betyr at Invocation-transaksjonen utløser utførelsen av innsatsfunksjonen (valg: String) på den smarte kontrakten.

RSA tilfeldig på blockchain

4. Vurder innsatsfunksjonen:

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

Funksjonen skriver et nytt spill til tilstanden til den smarte kontrakten. Nemlig:

  • Unik identifikator for et nytt spill (spill-ID)
  • Spillstatus = SENDT inn
  • Spillerens valg (segmentlengde 50)
  • Offentlig nøkkel
  • Potensielle gevinster (avhengig av spillerens innsats)

RSA tilfeldig på blockchain

Slik ser en datapost i blokkjeden ut (nøkkelverdi):

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

"Nøkkel" (nøkkel) - spill-ID nytt spill. De resterende dataene finnes i linjen i "verdi"-feltet. Disse oppføringene lagres i fanen Data smart kontrakt:

RSA tilfeldig på blockchain

RSA tilfeldig på blockchain

5. Serveren "ser" på den smarte kontrakten og finner den sendte transaksjonen (nytt spill) ved hjelp av blockchain Api. Spill-ID-en til det nye spillet er allerede registrert i blokkjeden, noe som betyr at det ikke lenger kan endres eller påvirkes

6. Serveren genererer en tilbaketrekningsfunksjon (gameId, rsaSign). For eksempel slik:

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

7. Serveren sender en Invocation-transaksjon til den smarte kontrakten (broadcast InvocationTx). Transaksjonen inneholder et kall til den dannede uttaksfunksjonen (gameId, rsaSign):

RSA tilfeldig på blockchain

Funksjonen inneholder spill-ID nytt spill og resultatet av RSA-signering av en unik identifikator med en privat nøkkel. Signaturresultatet er uendret.

Hva betyr det?

Vi tar den samme verdien (spill-ID) og bruker RSA-signaturmetoden på den. Vi vil alltid få samme resultat. Slik fungerer RSA-algoritmen. Det endelige tallet kan ikke manipuleres, siden spill-ID og resultatet av bruk av RSA ikke er kjent. Å velge et tall er også meningsløst.

8. Blockchain aksepterer transaksjonen. Den kjører tilbaketrekningsfunksjonen (gameId, rsaSign)

9. Inne i uttaksfunksjonen skjer uttak GenerateRandInt-funksjoner (spill-ID, rsaSign). Dette er en tilfeldig tallgenerator

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

alle - og det er et tilfeldig tall.

Først tas strengen, som er resultatet av RSA-signaturen spill-ID privat nøkkel (rsaSign). Deretter hashes med SHA-256 (sha256(rsaSign)).

Vi kan ikke forutsi utfallet av signaturen og påfølgende hashing. Derfor er det umulig å påvirke genereringen av et tilfeldig tall. For å få et tall i et bestemt område (for eksempel fra 1 til 100), bruk toInt-konverteringsfunksjonen og %100 (i likhet med mod).

I begynnelsen av artikkelen nevnte vi funksjonen rsaVerify(), som lar deg sjekke gyldigheten til en RSA-signatur ved å bruke en privat nøkkel mot en offentlig. Her er GenerateRandInt(gameId,rsaSign)-delen:

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

Den offentlige nøkkelen RSAPUBLIC og rsaSign-strengen sendes til inngangen. Signaturen kontrolleres for gyldighet. Nummeret genereres hvis sjekken er vellykket. Ellers vurderer systemet at signaturen ikke er gyldig (Ugyldig RSA-signatur).

Serveren må signere spill-ID-en med en privat nøkkel og sende en gyldig Rsa-signatur innen 2880 blokker. Parameteren konfigureres når den smarte kontrakten implementeres. Hvis ingenting skjer innen den tildelte tiden, vinner brukeren. I dette tilfellet må premien sendes til din adresse selv. Det viser seg at det "ikke er lønnsomt for serveren å jukse", fordi dette fører til tap. Nedenfor er et eksempel.

RSA tilfeldig på blockchain

Brukeren spiller Sier Roller. Jeg valgte 2 av de 6 sidene av kuben, innsatsen er 14 WAVES. Hvis serveren ikke sender en gyldig RSA-signatur til smartkontrakten innen den angitte tiden (2880 blokker), vil brukeren ta 34.44 BØLGER.

For å generere tall i spill bruker vi et orakel – et eksternt, ikke-blokkjedesystem. Serveren utfører en RSA-signatur av spill-IDen. Den smarte kontrakten sjekker gyldigheten av signaturen og bestemmer vinneren. Hvis serveren ikke sender noe, vinner brukeren automatisk.

Dette er en ærlig generasjonsmetode, fordi manipulasjon er teknisk umulig. Alle Tradisys-spill fungerer basert på den beskrevne algoritmen. Slik fungerer blockchain-spill. Alt er gjennomsiktig og kontrollerbart. Det er ingen analoger til et slikt system i noen annen blokkjede. Dette er ganske tilfeldig.

Kilde: www.habr.com

Legg til en kommentar