Losowe RSA na blockchainie

Jest problem - w zdecentralizowanej sieci trudno jest wygenerować liczbę losową. Prawie wszystkie blockchainy już się z tym spotkały. Rzeczywiście, w sieciach, w których nie ma zaufania między użytkownikami, utworzenie niezaprzeczalnej liczby losowej rozwiązuje wiele problemów.

W tym artykule powiemy, jak udało nam się rozwiązać problem na przykładzie gier. Pierwszym z nich był Fale Choinka. Do rozwoju potrzebowaliśmy generatora liczb losowych.

Losowe RSA na blockchainie

Początkowo planowaliśmy wygenerować liczbę na podstawie informacji z blockchainu. Potem jednak stało się jasne: liczbą można manipulować, co oznacza, że ​​rozwiązanie nie jest odpowiednie.

Wymyśliliśmy obejście: użyj schematu commit-expand. Serwer odgadł liczbę od 1 do 5, dodał do niej sól, a następnie zahaszował wynik za pomocą Funkcje Keccaka. Serwer wcześniej wdrożył inteligentną umowę z już zapisanym numerem. Okazuje się, że zabawa sprowadza się do odgadnięcia przez użytkownika liczby ukrytej pod hashem.

Gracz postawił zakład, a serwer wysłał ukryty numer i „sól” do inteligentnego kontraktu. Krótko mówiąc, odkrył karty. Następnie serwer sprawdził liczby i zdecydował, czy użytkownik wygrał, czy przegrał.

Jeśli serwer nie przesłał numeru lub „soli” do weryfikacji, użytkownik wygrał. W tym przypadku dla każdej gry konieczne było wcześniejsze wdrożenie inteligentnego kontraktu i uwzględnienie w nim potencjalnych wygranych. Okazało się to niewygodne, czasochłonne i kosztowne. W tamtym czasie nie było innego bezpiecznego rozwiązania.

Niedawno zespół Tradisys zaproponował dodanie funkcji do protokołu Waves rsaWeryfikacja(). Sprawdza ważność podpisu RSA na podstawie klucza publicznego i prywatnego. W rezultacie dodano tę funkcję.

Opracowaliśmy trzy gry: Wałek do kości, Rzut monetą и Jeździć na falach. Każdy z nich wykorzystuje technologię liczb losowych. Zastanówmy się, jak to działa.

Losowe RSA na blockchainie

Przyjrzyjmy się generowaniu liczby losowej na przykładzie Ride on Waves. Inteligentną umowę można znaleźć tutaj.

Przejdź do zakładki Scenariusz i wybierz Zdekompilowano. Zobaczysz inteligentny kod kontraktu (inaczej skrypt).

Losowe RSA na blockchainie

Inteligentny kod kontraktu zawiera zestaw funkcji. Te oznaczone jako @Callable można uruchomić za pomocą Transakcje wywoławcze. Interesują nas dwie funkcje: zakład и wycofać:

  • zakład func (wybór gracza)
  • funkcja wycofania (gameId, rsaSign)

1. Użytkownik wybiera długość segmentu i wielkość zakładu.

Losowe RSA na blockchainie

2. Klient tworzy funkcję zakładu. Dla powyższego zdjęcia byłoby to możliwe zakład("50").

3. Klient wysyła transakcję wywołania na adres inteligentnego kontraktu (broadcast InvocationTx). Transakcja zawiera funkcję zakładu jako parametr połączenia. Oznacza to, że transakcja Invocation wyzwala wykonanie funkcji zakładu (wybór: String) na inteligentnym kontrakcie.

Losowe RSA na blockchainie

4. Rozważ funkcję zakładu:

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

Funkcja zapisuje nową grę do stanu inteligentnego kontraktu. Mianowicie:

  • Unikalny identyfikator nowej gry (ID gry)
  • Stan gry = PRZESŁANO
  • Wybór gracza (długość segmentu 50)
  • Klucz publiczny
  • Potencjalne wygrane (w zależności od zakładu gracza)

Losowe RSA na blockchainie

Tak wygląda rekord danych w blockchainie (klucz-wartość):

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

„Klucz” (klucz) – ID gry Nowa gra. Pozostałe dane zawarte są w wierszu pola „wartość”. Wpisy te przechowywane są w zakładce Dane inteligentna umowa:

Losowe RSA na blockchainie

Losowe RSA na blockchainie

5. Serwer „przegląda” inteligentny kontrakt i znajduje wysłaną transakcję (nową grę) za pomocą blockchain Api. Identyfikator nowej gry jest już zapisany w łańcuchu bloków, co oznacza, że ​​nie można go już zmienić ani na niego wpływać

6. Serwer generuje funkcję wypłaty (gameId, rsaSign). Na przykład tak:

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

7. Serwer wysyła transakcję wywołania do inteligentnego kontraktu (rozgłoszenie InvocationTx). Transakcja zawiera wywołanie utworzonej funkcji wypłaty (gameId, rsaSign):

Losowe RSA na blockchainie

Funkcja zawiera ID gry nową grę i wynik podpisania przez RSA unikalnego identyfikatora kluczem prywatnym. Wynik podpisu pozostaje niezmieniony.

Co to znaczy?

Bierzemy tę samą wartość (identyfikator gry) i stosujemy do niej metodę podpisu RSA. Zawsze otrzymamy ten sam wynik. Tak działa algorytm RSA. Ostatecznej liczby nie można manipulować, ponieważ identyfikator gry i wynik zastosowania RSA nie są znane. Wybieranie numeru również nie ma sensu.

8. Blockchain akceptuje transakcję. Uruchamia funkcję wypłaty (gameId, rsaSign)

9. Wewnątrz funkcji wypłaty następuje wycofanie Generuj funkcjeRandInt (identyfikator gry, rsaSign). To jest generator liczb losowych

# @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 - i jest liczba losowa.

Najpierw pobierany jest ciąg znaków będący wynikiem podpisu RSA ID gry prywatny klucz (rsaSign). Następnie haszowano za pomocą SHA-256 (sha256(rsaSign)).

Nie możemy przewidzieć wyniku podpisu i późniejszego mieszania. Dlatego nie można wpływać na generowanie liczby losowej. Aby uzyskać liczbę z określonego zakresu (na przykład od 1 do 100), użyj funkcji konwersji toInt i %100 (podobnie jak mod).

Na początku artykułu wspomnieliśmy o funkcji rsaWeryfikacja(), która umożliwia sprawdzenie ważności podpisu RSA przy użyciu klucza prywatnego z kluczem publicznym. Oto część GenerateRandInt(gameId,rsaSign):

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

Na wejście przekazywany jest klucz publiczny RSAPUBLIC i ciąg znaków rsaSign. Podpis jest sprawdzany pod kątem ważności. Numer jest generowany w przypadku pomyślnego sprawdzenia. W przeciwnym razie system uzna, że ​​podpis jest nieprawidłowy (Nieprawidłowy podpis RSA).

Serwer musi podpisać identyfikator gry kluczem prywatnym i wysłać prawidłowy podpis Rsa w ciągu 2880 bloków. Parametr jest konfigurowany podczas wdrażania inteligentnej umowy. Jeżeli w wyznaczonym czasie nic się nie wydarzy, wygrywa użytkownik. W takim przypadku nagrodę należy wysłać samodzielnie na podany adres. Okazuje się, że serwerowi „nie opłaca się oszukiwać”, gdyż prowadzi to do strat. Poniżej znajduje się przykład.

Losowe RSA na blockchainie

Użytkownik gra Wałek do kości. Wybrałem 2 z 6 boków sześcianu, zakład to 14 FALI. Jeżeli serwer nie wyśle ​​ważnego podpisu RSA do inteligentnego kontraktu w określonym czasie (2880 bloków), użytkownik pobierze 34.44 FALE.

Do generowania liczb w grach wykorzystujemy Oracle – zewnętrzny system nie oparty na blockchainie. Serwer wykonuje podpis RSA identyfikatora gry. Inteligentna umowa sprawdza ważność podpisu i określa zwycięzcę. Jeśli serwer nic nie wyśle, użytkownik automatycznie wygrywa.

Jest to uczciwa metoda generowania, ponieważ manipulacja jest technicznie niemożliwa. Wszystkie gry Tradisys działają w oparciu o opisany algorytm. Tak działają gry oparte na blockchainie. Wszystko jest przejrzyste i sprawdzalne. Nie ma analogii takiego systemu w żadnym innym blockchainie. To jest uczciwy przypadek.

Źródło: www.habr.com

Dodaj komentarz