RSA slumpmässigt på blockchain

Det finns ett problem - det är svårt att generera ett slumptal i ett decentraliserat nätverk. Nästan alla blockkedjor har redan stött på detta. Faktum är att i nätverk där det inte finns något förtroende mellan användare, löser skapande av ett obestridligt slumptal många problem.

I den här artikeln berättar vi hur vi lyckades lösa problemet med hjälp av spel som exempel. Den första av dem var Vågor Xmas Tree. För utveckling behövde vi en slumptalsgenerator.

RSA slumpmässigt på blockchain

Till en början planerade vi att generera ett antal baserat på information från blockkedjan. Men då blev det klart: siffran kunde manipuleras, vilket betyder att lösningen inte är lämplig.

Vi kom på en lösning: använd commit-expand-schemat. Servern gissade ett nummer från 1 till 5, lade till ett salt till det och hashade sedan resultatet med hjälp av Keccak funktioner. Servern distribuerade det smarta kontraktet med det redan sparade numret i förväg. Det visar sig att spelet går ut på att användaren gissar numret som döljs av hashen.

Spelaren lade en insats och servern skickade det dolda numret och "saltet" till det smarta kontraktet. Enkelt uttryckt avslöjade han korten. Därefter kontrollerade servern siffrorna och avgjorde om användaren vann eller förlorade.

Om servern inte skickade ett nummer eller "salt" för verifiering, vann användaren. I det här fallet var det för varje spel nödvändigt att distribuera ett smart kontrakt i förväg och inkludera potentiella vinster i det. Det visade sig vara obekvämt, tidskrävande och dyrt. På den tiden fanns det ingen annan säker lösning.

Nyligen föreslog Tradisys-teamet att lägga till en funktion till Waves-protokollet rsaVerify(). Den kontrollerar giltigheten av RSA-signaturen baserat på den offentliga och privata nyckeln. Som ett resultat lades funktionen till.

Vi har utvecklat tre spel: Tärningsrulle, Coin Flip и Rida På Vågor. Var och en implementerar slumptalsteknologi. Låt oss ta reda på hur det fungerar.

RSA slumpmässigt på blockchain

Låt oss titta på att generera ett slumptal med Ride on Waves som exempel. Det smarta kontraktet kan hittas här.

Gå till flik Script och välj Dekompilerade. Du kommer att se den smarta kontraktskoden (alias script).

RSA slumpmässigt på blockchain

Den smarta kontraktskoden innehåller en uppsättning funktioner. De som är markerade @Callable kan utlösas med Anropstransaktioner. Vi är intresserade av två funktioner: satsa и dra tillbaka:

  • func bet (playerChoice)
  • func draw(gameId,rsaSign)

1. Användaren väljer segmentets längd och insatsstorlek.

RSA slumpmässigt på blockchain

2. Klienten skapar en insatsfunktion. För bilden ovan skulle det vara det bet("50").

3. Klienten skickar en Invocation-transaktion till den smarta kontraktsadressen (broadcast InvocationTx). Transaktionen innehåller satsningsfunktionen som en samtalsparameter. Detta innebär att anropstransaktionen utlöser exekveringen av satsningsfunktionen (val: String) på det smarta kontraktet.

RSA slumpmässigt på blockchain

4. Tänk på insatsfunktionen:

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

Funktionen skriver ett nytt spel till det smarta kontraktets tillstånd. Nämligen:

  • Unik identifierare för ett nytt spel (spel ID)
  • Spelstatus = SKÄNT
  • Spelarens val (segmentlängd 50)
  • Offentlig nyckel
  • Potentiella vinster (beroende på spelarens insats)

RSA slumpmässigt på blockchain

Så här ser en datapost i blockkedjan ut (nyckel-värde):

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

"Nyckel" (nyckel) - spel ID nytt spel. Återstående data finns på raden i fältet "värde". Dessa poster lagras i fliken Data smart kontrakt:

RSA slumpmässigt på blockchain

RSA slumpmässigt på blockchain

5. Servern "tittar" på det smarta kontraktet och hittar den skickade transaktionen (nytt spel) med hjälp av blockkedjans Api. Spel-id:t för det nya spelet är redan registrerat i blockkedjan, vilket innebär att det inte längre kan ändras eller påverkas

6. Servern genererar en uttagsfunktion (gameId, rsaSign). Till exempel så här:

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

7. Servern skickar en anropstransaktion till det smarta kontraktet (broadcast InvocationTx). Transaktionen innehåller ett anrop till den bildade uttagsfunktionen (gameId, rsaSign):

RSA slumpmässigt på blockchain

Funktionen innehåller spel ID nytt spel och resultatet av RSA-signering av en unik identifierare med en privat nyckel. Signaturresultatet är oförändrat.

Vad betyder det här?

Vi tar samma värde (spel-id) och tillämpar RSA-signaturmetoden på det. Vi kommer alltid att få samma resultat. Så här fungerar RSA-algoritmen. Det slutliga numret kan inte manipuleras, eftersom spelets ID och resultatet av att tillämpa RSA inte är kända. Att välja ett nummer är också meningslöst.

8. Blockchain accepterar transaktionen. Den kör uttagsfunktionen (gameId, rsaSign)

9. Inuti uttagsfunktionen sker uttag GenerateRandInt-funktioner (spel-ID, rsaSign). Detta är en slumptalsgenerator

# @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 - och det finns ett slumptal.

Först tas strängen, vilket är resultatet av RSA-signaturen spel ID privat nyckel (rsaSign). Hashade sedan med SHA-256 (sha256(rsaSign)).

Vi kan inte förutsäga resultatet av signaturen och efterföljande hash. Därför är det omöjligt att påverka genereringen av ett slumptal. För att få ett tal i ett visst intervall (till exempel från 1 till 100), använd toInt-konverteringsfunktionen och %100 (liknande mod).

I början av artikeln nämnde vi funktionen rsaVerify(), som låter dig kontrollera giltigheten av en RSA-signatur med hjälp av en privat nyckel mot en offentlig. Här är delen GenerateRandInt(gameId,rsaSign):

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

Den publika nyckeln RSAPUBLIC och rsaSign-strängen skickas till ingången. Signaturen kontrolleras för giltighet. Numret genereras om kontrollen lyckas. I annat fall anser systemet att signaturen inte är giltig (Ogiltig RSA-signatur).

Servern måste signera spel-id med en privat nyckel och skicka en giltig Rsa-signatur inom 2880 block. Parametern konfigureras när det smarta kontraktet distribueras. Om inget händer inom den tilldelade tiden vinner användaren. I så fall måste priset själv skickas till din adress. Det visar sig att det "inte är lönsamt för servern att fuska", eftersom detta leder till förlust. Nedan följer ett exempel.

RSA slumpmässigt på blockchain

Användaren spelar Tärningsrulle. Jag valde 2 av de 6 sidorna av kuben, insatsen är 14 VÅGOR. Om servern inte skickar en giltig RSA-signatur till det smarta kontraktet inom den angivna tiden (2880 block), kommer användaren att ta 34.44 VÅGOR.

För att generera siffror i spel använder vi ett orakel – ett externt, icke-blockkedjesystem. Servern utför en RSA-signatur av spel-id:t. Det smarta kontraktet kontrollerar signaturens giltighet och avgör vinnaren. Om servern inte skickar något, vinner användaren automatiskt.

Detta är en ärlig generationsmetod, eftersom manipulation är tekniskt omöjlig. Alla Tradisys-spel fungerar baserat på den beskrivna algoritmen. Så här fungerar blockchain-spel. Allt är transparent och verifierbart. Det finns inga analoger till ett sådant system i någon annan blockchain. Detta är en rättvis slumpmässighet.

Källa: will.com

Lägg en kommentar