Nastal problém – v decentralizované síti je obtížné vygenerovat náhodné číslo. S tím se již setkaly téměř všechny blockchainy. V sítích, kde mezi uživateli neexistuje žádná důvěra, totiž vytvoření nepopiratelného náhodného čísla řeší mnoho problémů.
V tomto článku vám řekneme, jak se nám podařilo problém vyřešit pomocí her jako příkladu. První z nich byl
Původně jsme plánovali vygenerovat číslo na základě informací z blockchainu. Pak se však ukázalo, že s číslem lze manipulovat, což znamená, že řešení není vhodné.
Přišli jsme s řešením: použijte schéma commit-expand. Server uhodl číslo od 1 do 5, přidal k němu sůl a výsledek pak hashoval pomocí
Hráč vsadil a server poslal skryté číslo a „sůl“ do chytré smlouvy. Jednoduše řečeno, odhalil karty. Poté server zkontroloval čísla a rozhodl, zda uživatel vyhrál nebo prohrál.
Pokud server neposlal číslo nebo „sůl“ pro ověření, uživatel vyhrál. V tomto případě bylo pro každou hru nutné předem nasadit chytrý kontrakt a započítat do něj případné výhry. Ukázalo se, že je to nepohodlné, časově náročné a drahé. V té době neexistovalo jiné bezpečné řešení.
Nedávno tým Tradisys navrhl přidání funkce do protokolu Waves rsaVerify(). Kontroluje platnost RSA podpisu na základě veřejného a soukromého klíče. V důsledku toho byla funkce přidána.
Vyvinuli jsme tři hry:
Podívejme se na generování náhodného čísla pomocí příkladu Ride on Waves. Chytrou smlouvu lze nalézt
Přejděte na kartu Scénář a vyberte Dekompilováno. Uvidíte kód inteligentní smlouvy (aka skript).
Kód inteligentní smlouvy obsahuje sadu funkcí. Ty označené jako @Callable lze spustit pomocí Vyvolávací transakce. Zajímají nás dvě funkce: sázet и zrušit:
- func bet (playerChoice)
- func draw(gameId,rsaSign)
1. Uživatel zvolí délku segmentu a velikost sázky.
2. Klient vytvoří sázkovou funkci. Pro obrázek výše by to bylo sázka("50").
3. Klient odešle transakci Invocation na adresu smart kontraktu (broadcast InvocationTx). Transakce obsahuje funkci sázky jako parametr volání. To znamená, že transakce vyvolání spouští provedení funkce sázky (volba: String) na smart kontraktu.
4. Zvažte funkci sázky:
@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)))
}
}
Funkce zapíše novou hru do stavu chytré smlouvy. A to:
- Jedinečný identifikátor pro novou hru (ID hry)
- Stav hry = ODEVZDÁNO
- Volba hráče (délka segmentu 50)
- Veřejný klíč
- Potenciální výhry (v závislosti na sázce hráče)
Takto vypadá datový záznam v blockchainu (klíč-hodnota):
{
"type": "string",
"value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229",
"key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx"
}
"Klíč" (klíč) - id hry nová hra. Zbývající údaje jsou obsaženy v řádku pole „hodnota“. Tyto záznamy jsou uloženy v záložce Data chytrá smlouva:
5. Server se „podívá“ na smart kontrakt a najde odeslanou transakci (novou hru) pomocí blockchain Api. ID hry nové hry je již zaznamenáno v blockchainu, což znamená, že jej již nelze změnit ani ovlivnit
6. Server vygeneruje funkci stažení (gameId, rsaSign). Například takto:
withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==")
7. Server odešle transakci Invocation do chytré smlouvy (broadcast InvocationTx). Transakce obsahuje volání vytvořené funkce stažení (gameId, rsaSign):
Funkce obsahuje id hry nová hra a výsledek RSA podepsání unikátního identifikátoru s privátním klíčem. Výsledek podpisu se nemění.
Co to znamená?
Vezmeme stejnou hodnotu (id hry) a aplikujeme na ni metodu podpisu RSA. Vždy dostaneme stejný výsledek. Takto funguje algoritmus RSA. S konečným číslem nelze manipulovat, protože id hry ani výsledek použití RSA nejsou známy. Vybírání čísla je také zbytečné.
8. Blockchain přijímá transakci. Spouští funkci stažení (gameId, rsaSign)
9. Uvnitř funkce vytažení dojde k vytažení GenerateRandInt funkce (gameId, rsaSign). Toto je generátor náhodných čísel
# @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")
}
vše - a existuje náhodné číslo.
Nejprve se vezme řetězec, který je výsledkem podpisu RSA id hry soukromý klíč (rsaSign). Poté hashujte pomocí SHA-256 (sha256(rsaSign)).
Nemůžeme předvídat výsledek podpisu a následného hashování. Nelze tedy ovlivnit generování náhodného čísla. Chcete-li získat číslo v určitém rozsahu (například od 1 do 100), použijte převodní funkci na toInt a %100 (podobně jako
Na začátku článku jsme zmínili funkci rsaVerify(), který umožňuje ověřit platnost RSA podpisu pomocí soukromého klíče proti veřejnému. Zde je část GenerateRandInt(gameId,rsaSign):
rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
Na vstup je předán veřejný klíč RSAPUBLIC a řetězec rsaSign. Zkontroluje se platnost podpisu. Číslo se vygeneruje, pokud je kontrola úspěšná. V opačném případě systém považuje podpis za neplatný (Neplatný podpis RSA).
Server musí podepsat ID hry soukromým klíčem a odeslat platný podpis Rsa do 2880 bloků. Parametr se konfiguruje při nasazování chytré smlouvy. Pokud se ve stanoveném čase nic nestane, uživatel vyhrává. V takovém případě je třeba výhru zaslat na vaši adresu sami. Ukazuje se, že „pro server není výhodné podvádět“, protože to vede ke ztrátě. Níže je uveden příklad.
Uživatel hraje
Pro generování čísel ve hrách používáme oracle – externí, neblockchainový systém. Server provede RSA podpis ID hry. Smart kontrakt zkontroluje platnost podpisu a určí vítěze. Pokud server nic nepošle, uživatel automaticky vyhrává.
Jedná se o poctivou generační metodu, protože manipulace je technicky nemožná. Všechny hry Tradisys fungují na základě popsaného algoritmu. Takhle fungují blockchainové hry. Vše je transparentní a ověřitelné. V žádném jiném blockchainu neexistují obdoby takového systému. Tohle je docela náhoda.
Zdroj: www.habr.com