RSA véletlenszerű a blokkláncon

Van egy probléma - nehéz véletlen számot generálni egy decentralizált hálózatban. Szinte minden blokklánc találkozott már ezzel. Valójában azokban a hálózatokban, ahol nincs bizalom a felhasználók között, egy tagadhatatlan véletlenszám létrehozása sok problémát megold.

Ebben a cikkben bemutatjuk, hogyan tudtuk megoldani a problémát, például játékok segítségével. Az első közülük az volt Waves karácsonyfa. A fejlesztéshez véletlenszám-generátorra volt szükségünk.

RSA véletlenszerű a blokkláncon

Kezdetben azt terveztük, hogy egy számot generálunk a blokkláncból származó információk alapján. Ekkor azonban kiderült: a szám manipulálható, vagyis a megoldás nem megfelelő.

Találtunk egy kerülő megoldást: használjuk a commit-expand sémát. A szerver kitalált egy számot 1-től 5-ig, hozzáadta a sót, majd kivonatolta az eredményt Keccak függvények. A szerver előre telepítette az intelligens szerződést a már mentett számmal. Kiderül, hogy a játék lényege, hogy a felhasználó kitalálja a hash által elrejtett számot.

A játékos fogadást tett, a szerver pedig elküldte a rejtett számot és a „sót” az okosszerződésbe. Egyszerűen fogalmazva, felfedte a kártyákat. Ezt követően a szerver ellenőrizte a számokat, és eldöntötte, hogy a felhasználó nyert vagy veszített.

Ha a szerver nem küldött számot vagy „sót” ellenőrzésre, a felhasználó nyert. Ebben az esetben minden játékhoz előre kellett kötni egy intelligens szerződést, és bele kellett foglalni a lehetséges nyereményeket. Kiderült, hogy kényelmetlen, időigényes és drága. Akkoriban nem volt más biztonságos megoldás.

Nemrég a Tradisys csapata javasolta egy funkció hozzáadását a Waves protokollhoz rsaVerify(). A nyilvános és privát kulcs alapján ellenőrzi az RSA aláírás érvényességét. Ennek eredményeként a funkció hozzáadásra került.

Három játékot fejlesztettünk ki: Kockahenger, Coin Flip и Ride On Waves. Mindegyik véletlenszám-technológiát valósít meg. Kitaláljuk, hogyan működik.

RSA véletlenszerű a blokkláncon

Nézzük meg egy véletlen szám generálását a Ride on Waves példával. Az okos szerződés megtalálható itt.

Lépjen a fülre Forgatókönyv és válassza ki Dekompilált. Látni fogja az intelligens szerződés kódját (más néven szkriptet).

RSA véletlenszerű a blokkláncon

Az intelligens szerződés kódja egy sor funkciót tartalmaz. A @Callable megjelölésűek a használatával indíthatók el Behívási tranzakciók. Két funkcióra vagyunk kíváncsiak: tét и visszavonul:

  • func fogadás (játékos választás)
  • funkció visszavonása(gameId,rsaSign)

1. A felhasználó kiválasztja a szegmens hosszát és a tét nagyságát.

RSA véletlenszerű a blokkláncon

2. Az ügyfél létrehoz egy fogadási függvényt. A fenti képen az lenne bet("50").

3. Az ügyfél egy Invocation tranzakciót küld az intelligens szerződés címére (broadcast InvocationTx). A tranzakció hívási paraméterként tartalmazza a fogadás függvényt. Ez azt jelenti, hogy az Invocation tranzakció elindítja a fogadási funkció (választható: String) végrehajtását az intelligens szerződésen.

RSA véletlenszerű a blokkláncon

4. Tekintsük a fogadási függvényt:

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

A függvény új játékot ír az intelligens szerződés állapotába. Ugyanis:

  • Egyedi azonosító egy új játékhoz (játékazonosító)
  • A játék állapota = BEADVA
  • A játékos választása (szakasz hossza 50)
  • Nyilvános kulcs
  • Potenciális nyeremények (a játékos fogadásától függően)

RSA véletlenszerű a blokkláncon

Így néz ki egy adatrekord a blokkláncban (kulcsérték):

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

"Kulcs" (kulcs) – játék id új játék. A fennmaradó adatokat az „érték” mező sora tartalmazza. Ezeket a bejegyzéseket a lap tárolja dátum okos szerződés:

RSA véletlenszerű a blokkláncon

RSA véletlenszerű a blokkláncon

5. A szerver „megnézi” az intelligens szerződést, és a blokklánc Api segítségével megtalálja az elküldött tranzakciót (új játékot). Az új játék játékazonosítója már rögzítve van a blokkláncban, ami azt jelenti, hogy már nem módosítható vagy befolyásolható

6. A szerver egy visszavonási függvényt generál (gameId, rsaSign). Például így:

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

7. A szerver Invocation tranzakciót küld az intelligens szerződésnek (broadcast InvocationTx). A tranzakció a kialakított visszavonási függvény hívását tartalmazza (gameId, rsaSign):

RSA véletlenszerű a blokkláncon

A függvény tartalmazza játék id új játék, és egy egyedi azonosító privát kulccsal történő RSA aláírásának eredménye. Az aláírás eredménye változatlan.

Mit jelent ez?

Ugyanazt az értéket (játékazonosítót) vesszük, és az RSA aláírási módszert alkalmazzuk rá. Mindig ugyanazt az eredményt fogjuk elérni. Így működik az RSA algoritmus. A végső szám nem módosítható, mivel a játék azonosítója és az RSA alkalmazásának eredménye nem ismert. A szám kiválasztása szintén értelmetlen.

8. A Blockchain elfogadja a tranzakciót. Futtatja a visszavonási függvényt (gameId, rsaSign)

9. A visszavonási funkción belül kivonás történik GenerateRandInt függvények (gameId, rsaSign). Ez egy véletlenszám-generátor

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

sor - és van egy véletlen szám.

Először a karakterláncot veszik, amely az RSA aláírás eredménye játék id privát kulcs (rsaSign). Ezután kivonatolva SHA-256 (sha256 (rsaSign)).

Nem tudjuk megjósolni az aláírás és az azt követő hash kimenetelét. Ezért lehetetlen befolyásolni egy véletlen szám generálását. Ha egy bizonyos tartományban (például 1-től 100-ig) szeretne számot kapni, használja a toInt konverziós függvényt és a %100-at (hasonlóan mod).

A cikk elején említettük a funkciót rsaVerify(), amely lehetővé teszi egy RSA-aláírás érvényességének ellenőrzését egy privát kulccsal a nyilvános kulcshoz képest. Itt van a GenerateRandInt(gameId,rsaSign) rész:

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

Az RSAPUBLIC nyilvános kulcs és az rsaSign karakterlánc átadásra kerül a bemenetnek. Az aláírás érvényességét ellenőrizzük. A szám akkor jön létre, ha az ellenőrzés sikeres. Ellenkező esetben a rendszer úgy ítéli meg, hogy az aláírás érvénytelen (Érvénytelen RSA aláírás).

A szervernek alá kell írnia a játékazonosítót egy privát kulccsal, és 2880 blokkon belül érvényes Rsa aláírást kell küldenie. A paraméter az intelligens szerződés telepítésekor van konfigurálva. Ha semmi sem történik a megadott időn belül, a felhasználó nyer. Ebben az esetben a nyereményt Önnek kell elküldenie a címére. Kiderült, hogy „nem jövedelmező a szervernek csalni”, mert ez veszteséghez vezet. Alább egy példa.

RSA véletlenszerű a blokkláncon

A felhasználó játszik Kockahenger. A kocka 2 oldala közül 6-t választottam, a tét 14 WAVES. Ha a szerver a megadott időn belül (2880 blokk) nem küld érvényes RSA-aláírást az intelligens szerződéshez, a felhasználó 34.44 WAVES-t vesz fel.

Számok generálásához a játékokban orákulumot használunk - egy külső, nem blokklánc-rendszert. A szerver végrehajtja a játékazonosító RSA aláírását. Az intelligens szerződés ellenőrzi az aláírás érvényességét és meghatározza a nyertest. Ha a szerver nem küld semmit, akkor automatikusan a felhasználó nyer.

Ez egy őszinte generációs módszer, mert a manipuláció technikailag lehetetlen. Minden Tradisys játék a leírt algoritmus alapján működik. Így működnek a blokklánc játékok. Minden átlátható és ellenőrizhető. Nincsenek analógjai egy ilyen rendszernek egyetlen másik blokkláncban sem. Ez egy tisztességes véletlen.

Forrás: will.com

Hozzászólás