RSA satunnainen lohkoketjussa

On ongelma - on vaikea luoda satunnaislukua hajautetussa verkossa. Melkein kaikki lohkoketjut ovat jo kohdanneet tämän. Verkoissa, joissa käyttäjien välillä ei ole luottamusta, kiistattoman satunnaisluvun luominen ratkaisee monia ongelmia.

Tässä artikkelissa kerromme sinulle, kuinka onnistuimme ratkaisemaan ongelman käyttämällä pelejä esimerkkinä. Ensimmäinen niistä oli Waves joulupuu. Kehitystä varten tarvitsimme satunnaislukugeneraattorin.

RSA satunnainen lohkoketjussa

Aluksi suunnittelimme luovamme numeron lohkoketjun tietojen perusteella. Sitten kuitenkin kävi selväksi: numeroa voi manipuloida, mikä tarkoittaa, että ratkaisu ei ole sopiva.

Keksimme kiertotavan: käytä commit-expand -mallia. Palvelin arvasi luvun 1-5, lisäsi siihen suolan ja tiivisti tuloksen käyttämällä Keccak-toiminnot. Palvelin otti älykkään sopimuksen käyttöön jo tallennetulla numerolla etukäteen. Osoittautuu, että peli tiivistyy siihen, että käyttäjä arvaa hashin piilottaman numeron.

Pelaaja asetti vedon, ja palvelin lähetti piilotetun numeron ja "suolan" älysopimukseen. Yksinkertaisesti sanottuna hän paljasti kortit. Sen jälkeen palvelin tarkisti numerot ja päätti, voittiko vai hävisikö käyttäjä.

Jos palvelin ei lähettänyt numeroa tai "suolaa" vahvistusta varten, käyttäjä voitti. Tässä tapauksessa jokaista peliä varten oli tarpeen ottaa käyttöön älykäs sopimus etukäteen ja sisällyttää siihen mahdolliset voitot. Se osoittautui hankalaksi, aikaa vieväksi ja kalliiksi. Muuta turvallista ratkaisua ei tuolloin ollut.

Äskettäin Tradisys-tiimi ehdotti toiminnon lisäämistä Waves-protokollaan rsaVerify(). Se tarkistaa RSA-allekirjoituksen voimassaolon julkisen ja yksityisen avaimen perusteella. Tämän seurauksena ominaisuus lisättiin.

Olemme kehittäneet kolme peliä: Nopparulla, Coin Flip и Ride On Waves. Jokainen käyttää satunnaislukutekniikkaa. Selvitetään, miten se toimii.

RSA satunnainen lohkoketjussa

Katsotaanpa satunnaisluvun luomista käyttämällä esimerkkinä Ride on Waves -ohjelmaa. Älykäs sopimus löytyy täällä.

Siirry välilehdelle Käsikirjoitus ja valitse Purettu. Näet älykkään sopimuskoodin (alias script).

RSA satunnainen lohkoketjussa

Älykäs sopimuskoodi sisältää joukon toimintoja. @Callable-merkityt voidaan käynnistää käyttämällä Kutsutapahtumat. Olemme kiinnostuneita kahdesta toiminnosta: veto и peruuttaa:

  • func-veto (pelaajan valinta)
  • toiminto vetää (gameId,rsaSign)

1. Käyttäjä valitsee segmentin pituuden ja panoksen koon.

RSA satunnainen lohkoketjussa

2. Asiakas luo vetotoiminnon. Yllä olevalle kuvalle se olisi veto ("50").

3. Asiakas lähettää kutsutapahtuman älykkään sopimusosoitteeseen (broadcast InvocationTx). Tapahtuma sisältää panostoiminnon kutsuparametrina. Tämä tarkoittaa, että Invocation-tapahtuma laukaisee panostoiminnon (valinta: String) suorittamisen älykkäässä sopimuksessa.

RSA satunnainen lohkoketjussa

4. Harkitse vetotoimintoa:

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

Toiminto kirjoittaa uuden pelin älysopimuksen tilaan. Nimittäin:

  • Ainutlaatuinen tunniste uudelle pelille (pelitunnus)
  • Pelin tila = LÄHETETTY
  • Pelaajan valinta (segmentin pituus 50)
  • Julkinen avain
  • Mahdolliset voitot (riippuen pelaajan panoksesta)

RSA satunnainen lohkoketjussa

Tältä lohkoketjun datatietue näyttää (avainarvo):

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

"Avain" (avain) – pelin tunnus Uusi peli. Loput tiedot sisältyvät "arvo"-kentän riville. Nämä merkinnät tallennetaan välilehdelle Päiväys älykäs sopimus:

RSA satunnainen lohkoketjussa

RSA satunnainen lohkoketjussa

5. Palvelin "katsoi" älysopimusta ja löytää lähetetyn tapahtuman (uuden pelin) lohkoketju Api:n avulla. Uuden pelin pelitunnus on jo tallennettu lohkoketjuun, joten siihen ei voi enää muuttaa tai vaikuttaa

6. Palvelin luo poistofunktion (gameId, rsaSign). Esimerkiksi näin:

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

7. Palvelin lähettää kutsutapahtuman älykkäälle sopimukselle (broadcast InvocationTx). Tapahtuma sisältää kutsun muodostettuun nostotoimintoon (gameId, rsaSign):

RSA satunnainen lohkoketjussa

Funktio sisältää pelin tunnus uusi peli ja tulos yksilöllisen tunnisteen RSA-allekirjoituksesta yksityisellä avaimella. Allekirjoitustulos on ennallaan.

Mitä tämä tarkoittaa?

Otamme saman arvon (pelitunnus) ja käytämme siihen RSA-allekirjoitusmenetelmää. Saamme aina saman tuloksen. Näin RSA-algoritmi toimii. Lopullista numeroa ei voi manipuloida, koska pelitunnusta ja RSA-sovelluksen tulosta ei tiedetä. Numeron valitseminen on myös turhaa.

8. Blockchain hyväksyy tapahtuman. Se suorittaa nostotoiminnon (gameId, rsaSign)

9. Nostotoiminnon sisällä tapahtuu vetäytymistä GenerateRandInt-funktiot (gameId, rsaSign). Tämä on satunnaislukugeneraattori

# @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 siellä on satunnainen luku.

Ensin otetaan merkkijono, joka on RSA-allekirjoituksen tulos pelin tunnus yksityinen avain (rsaSign). Sitten tiivistetty SHA-256:lla (sha256(rsaSign)).

Emme voi ennustaa allekirjoituksen ja myöhemmän hajautustuloksen tulosta. Siksi satunnaisluvun muodostumiseen on mahdotonta vaikuttaa. Jos haluat saada luvun tietyltä alueelta (esimerkiksi 1-100), käytä toInt-muunnosfunktiota ja %100 (samanlainen kuin mod).

Mainitsimme artikkelin alussa toiminnon rsaVerify(), jonka avulla voit tarkistaa RSA-allekirjoituksen kelvollisuuden käyttämällä yksityistä avainta julkiseen avaimeen verrattuna. Tässä on GenerateRandInt(gameId,rsaSign) osa:

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

Julkinen avain RSAPUBLIC ja rsaSign-merkkijono välitetään syötteeseen. Allekirjoituksen kelvollisuus tarkistetaan. Numero luodaan, jos tarkistus onnistuu. Muussa tapauksessa järjestelmä katsoo, että allekirjoitus ei ole kelvollinen (Invalid RSA signature).

Palvelimen on allekirjoitettava pelitunnus yksityisellä avaimella ja lähetettävä kelvollinen Rsa-allekirjoitus 2880 lohkon sisällä. Parametri määritetään älykästä sopimusta otettaessa käyttöön. Jos mitään ei tapahdu annetussa ajassa, käyttäjä voittaa. Tässä tapauksessa palkinto tulee lähettää osoitteeseesi itse. Osoittautuu, että "palvelimelle ei ole kannattavaa huijata", koska tämä johtaa tappioon. Alla on esimerkki.

RSA satunnainen lohkoketjussa

Käyttäjä pelaa Nopparulla. Valitsin 2 kuution kuudesta sivusta, panos on 6 AALTOA. Jos palvelin ei lähetä kelvollista RSA-allekirjoitusta älysopimukseen määritetyn ajan kuluessa (14 lohkoa), käyttäjä ottaa 2880 AALTOA.

Numeroiden luomiseen peleissä käytämme oraakkelia - ulkoista, ei-blockchain-järjestelmää. Palvelin suorittaa pelitunnuksen RSA-allekirjoituksen. Älykäs sopimus tarkistaa allekirjoituksen oikeellisuuden ja määrittää voittajan. Jos palvelin ei lähetä mitään, käyttäjä voittaa automaattisesti.

Tämä on rehellinen sukupolvimenetelmä, koska manipulointi on teknisesti mahdotonta. Kaikki Tradisys-pelit toimivat kuvatun algoritmin mukaan. Näin lohkoketjupelit toimivat. Kaikki on läpinäkyvää ja tarkistettavissa. Tällaiselle järjestelmälle ei ole analogeja missään muussa lohkoketjussa. Tämä on reilu satunnainen.

Lähde: will.com

Lisää kommentti