RSA nasumično na blockchainu

Postoji problem - teško je generirati slučajni broj u decentraliziranoj mreži. Gotovo svi blockchaini već su se susreli s tim. Doista, u mrežama u kojima nema povjerenja među korisnicima, stvaranje nepobitnog slučajnog broja rješava mnoge probleme.

U ovom članku ćemo vam reći kako smo uspjeli riješiti problem koristeći igre kao primjer. Prvi od njih bio je Valovi Božićno drvce. Za razvoj nam je trebao generator slučajnih brojeva.

RSA nasumično na blockchainu

U početku smo planirali generirati broj na temelju informacija iz blockchaina. No, tada je postalo jasno: brojkom se može manipulirati, što znači da rješenje nije prikladno.

Smislili smo zaobilazno rješenje: upotrijebite shemu commit-expand. Poslužitelj je pogodio broj od 1 do 5, dodao mu sol, a zatim raspršio rezultat pomoću Keccak funkcije. Poslužitelj je unaprijed implementirao pametni ugovor s već spremljenim brojem. Ispostavilo se da se igra svodi na to da korisnik pogađa broj koji skriva hash.

Igrač je stavio okladu, a server je poslao skriveni broj i "sol" pametnom ugovoru. Jednostavnim riječima, otkrio je karte. Nakon toga poslužitelj je provjerio brojeve i odlučio je li korisnik pobijedio ili izgubio.

Ako poslužitelj nije poslao broj ili "sol" na provjeru, korisnik je pobijedio. U ovom slučaju, za svaku je igru ​​bilo potrebno unaprijed implementirati pametni ugovor i u njega uključiti potencijalne dobitke. Pokazalo se da je to nezgodno, dugotrajno i skupo. U to vrijeme nije bilo drugog sigurnog rješenja.

Nedavno je Tradisys tim predložio dodavanje funkcije Waves protokolu rsaVerify(). Provjerava valjanost RSA potpisa na temelju javnog i privatnog ključa. Kao rezultat toga, značajka je dodana.

Razvili smo tri igre: Bacanje kockica, Coin Flip и Vožnja na valovima. Svaki od njih implementira tehnologiju nasumičnog broja. Hajdemo shvatiti kako to funkcionira.

RSA nasumično na blockchainu

Pogledajmo generiranje nasumičnog broja koristeći Ride on Waves kao primjer. Pametni ugovor se može pronaći здесь.

Idite na karticu Script i odaberite Dekompilirano. Vidjet ćete kod pametnog ugovora (aka skripta).

RSA nasumično na blockchainu

Kod pametnog ugovora sadrži skup funkcija. One označene kao @Callable mogu se pokrenuti pomoću Transakcije pozivanja. Zanimaju nas dvije funkcije: ulog и povući:

  • func ulog (playerChoice)
  • funkcija povlačenja(gameId,rsaSign)

1. Korisnik odabire duljinu segmenta i veličinu uloga.

RSA nasumično na blockchainu

2. Klijent kreira funkciju oklade. Za gornju sliku bilo bi ulog("50").

3. Klijent šalje Invocation transakciju na adresu pametnog ugovora (broadcast InvocationTx). Transakcija sadrži funkciju klađenja kao parametar poziva. To znači da transakcija Invocation pokreće izvršenje funkcije klađenja (izbor: niz) na pametnom ugovoru.

RSA nasumično na blockchainu

4. Razmotrite funkciju oklade:

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

Funkcija upisuje novu igru ​​u stanje pametnog ugovora. Naime:

  • Jedinstveni identifikator za novu igru (ID igre)
  • Stanje igre = POSLANO
  • Izbor igrača (duljina segmenta 50)
  • Javni ključ
  • Potencijalni dobici (ovisno o ulogu igrača)

RSA nasumično na blockchainu

Ovako izgleda zapis podataka u blockchainu (ključ-vrijednost):

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

"Ključ" (ključ) – id igre Nova igra. Preostali podaci nalaze se u retku polja "vrijednost". Ti su unosi pohranjeni u kartici Datum pametni ugovor:

RSA nasumično na blockchainu

RSA nasumično na blockchainu

5. Poslužitelj “gleda” pametni ugovor i pronalazi poslanu transakciju (nova igra) koristeći blockchain Api. Game ID nove igre već je zabilježen u blockchainu, što znači da se više ne može mijenjati ili utjecati na njega

6. Poslužitelj generira funkciju povlačenja (gameId, rsaSign). Na primjer, ovako:

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

7. Poslužitelj šalje transakciju Invocation pametnom ugovoru (broadcast InvocationTx). Transakcija sadrži poziv formiranoj funkciji povlačenja (gameId, rsaSign):

RSA nasumično na blockchainu

Funkcija sadrži id igre nova igra i rezultat RSA potpisivanja jedinstvenog identifikatora s privatnim ključem. Rezultat potpisa je nepromijenjen.

Što to znači?

Uzimamo istu vrijednost (id igre) i na nju primjenjujemo metodu RSA potpisa. Uvijek ćemo dobiti isti rezultat. Ovako radi RSA algoritam. Konačnim brojem se ne može manipulirati jer ID igre i rezultat primjene RSA nisu poznati. Biranje broja također je besmisleno.

8. Blockchain prihvaća transakciju. Pokreće funkciju povlačenja (gameId, rsaSign)

9. Unutar funkcije povlačenja dolazi do povlačenja GenerateRandInt funkcije (Id igre, rsaSign). Ovo je generator slučajnih brojeva

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

red - i tu je nasumični broj.

Prvo se uzima niz, koji je rezultat RSA potpisa id igre privatni ključ (rsaSign). Zatim se rasprši s SHA-256 (sha256(rsaSign)).

Ne možemo predvidjeti ishod potpisa i naknadnog raspršivanja. Stoga je nemoguće utjecati na generiranje slučajnog broja. Da biste dobili broj u određenom rasponu (na primjer, od 1 do 100), upotrijebite funkciju pretvorbe u Int i %100 (slično mod).

Na početku članka spomenuli smo funkciju rsaVerify(), koji vam omogućuje da provjerite valjanost RSA potpisa korištenjem privatnog ključa u odnosu na javni. Evo dijela GenerateRandInt(gameId,rsaSign):

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

Javni ključ RSAPUBLIC i niz rsaSign prosljeđuju se na ulaz. Provjerava se valjanost potpisa. Broj se generira ako je provjera uspješna. U suprotnom, sustav smatra da potpis nije valjan (Invalid RSA signature).

Poslužitelj mora potpisati ID igre privatnim ključem i poslati važeći RSA potpis unutar 2880 blokova. Parametar se konfigurira prilikom implementacije pametnog ugovora. Ako se ništa ne dogodi unutar dodijeljenog vremena, korisnik pobjeđuje. U tom slučaju nagradu morate sami poslati na svoju adresu. Ispada da "nije isplativo za poslužitelja varati", jer to dovodi do gubitka. Ispod je primjer.

RSA nasumično na blockchainu

Korisnik igra Bacanje kockica. Izabrao sam 2 od 6 stranica kocke, ulog je 14 VALOVA. Ako poslužitelj ne pošalje valjani RSA potpis pametnom ugovoru unutar navedenog vremena (2880 blokova), korisnik će uzeti 34.44 VALOVA.

Za generiranje brojeva u igrama koristimo oracle - vanjski sustav koji nije povezan s blokovima. Poslužitelj izvodi RSA potpis ID-a igre. Pametni ugovor provjerava valjanost potpisa i određuje pobjednika. Ako poslužitelj ne pošalje ništa, korisnik automatski pobjeđuje.

Ovo je metoda poštene generacije, jer je manipulacija tehnički nemoguća. Sve Tradisys igre rade na temelju opisanog algoritma. Ovako funkcioniraju blockchain igre. Sve je transparentno i provjerljivo. Nema analoga takvog sustava ni u jednom drugom blockchainu. Ovo je prilično nasumično.

Izvor: www.habr.com

Dodajte komentar