RSA случаен на blockchain

Има проблем - трудно е да се генерира произволно число в децентрализирана мрежа. Почти всички блокчейни вече са се сблъскали с това. Наистина, в мрежи, където няма доверие между потребителите, създаването на неоспоримо произволно число решава много проблеми.

В тази статия ви разказваме как успяхме да разрешим проблема, използвайки игри като пример. Първият от тях беше Вълни Коледно дърво. За разработката ни беше необходим генератор на произволни числа.

RSA случаен на blockchain

Първоначално планирахме да генерираме число въз основа на информация от блокчейна. Тогава обаче стана ясно: числото може да бъде манипулирано, което означава, че решението не е подходящо.

Измислихме заобиколно решение: използвайте схемата commit-expand. Сървърът позна число от 1 до 5, добави сол към него и след това хешира резултата с помощта на Keccak функции. Сървърът разгърна интелигентния договор с вече запазения номер предварително. Оказва се, че играта се свежда до потребителя да познае числото, скрито от хеша.

Играчът направи залог и сървърът изпрати скритото число и „солта“ към интелигентния договор. С прости думи той разкри картите. След това сървърът провери числата и реши дали потребителят спечели или загуби.

Ако сървърът не изпрати номер или „сол“ за проверка, потребителят печели. В този случай за всяка игра беше необходимо предварително да се разгърне интелигентен договор и да се включат потенциални печалби в него. Оказа се неудобно, времеемко и скъпо. По това време нямаше друго безопасно решение.

Наскоро екипът на Tradisys предложи добавяне на функция към протокола Waves rsaVerify(). Той проверява валидността на RSA подписа въз основа на публичния и частния ключ. В резултат на това функцията беше добавена.

Разработихме три игри: Казва Roller, Coin Flip и Карай върху вълни. Всеки от тях прилага технология за произволни числа. Нека да разберем как работи.

RSA случаен на blockchain

Нека да разгледаме генерирането на произволно число, използвайки Ride on Waves като пример. Интелигентният договор може да бъде намерен тук.

Отидете в раздела Сценарий и изберете Декомпилиран. Ще видите кода на интелигентния договор (известен още като скрипт).

RSA случаен на blockchain

Кодът на интелигентния договор съдържа набор от функции. Тези, маркирани като @Callable, могат да бъдат стартирани с помощта на Извикващи транзакции. Ние се интересуваме от две функции: заложат и оттегли:

  • func залог (playerChoice)
  • func тегли (gameId,rsaSign)

1. Потребителят избира дължината на сегмента и размера на залога.

RSA случаен на blockchain

2. Клиентът създава функция за залагане. За изображението по-горе би било залог ("50").

3. Клиентът изпраща транзакция Invocation до адреса на интелигентния договор (broadcast InvocationTx). Транзакцията съдържа функцията за залагане като параметър за повикване. Това означава, че транзакцията Invocation задейства изпълнението на функцията за залагане (избор: String) на интелигентния договор.

RSA случаен на blockchain

4. Помислете за функцията за залагане:

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

Функцията записва нова игра в състоянието на интелигентния договор. а именно:

  • Уникален идентификатор за нова игра (ID на играта)
  • Състояние на играта = ИЗПРАТЕНО
  • Избор на играча (дължина на сегмента 50)
  • Публичен ключ
  • Потенциални печалби (в зависимост от залога на играча)

RSA случаен на blockchain

Ето как изглежда запис на данни в блокчейна (ключ-стойност):

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

"Ключ" (ключ) – идентификатор на играта нова игра. Останалите данни се съдържат в реда на полето „стойност“. Тези записи се съхраняват в раздела Дата интелигентен договор:

RSA случаен на blockchain

RSA случаен на blockchain

5. Сървърът „преглежда“ интелигентния договор и намира изпратената транзакция (нова игра) с помощта на блокчейн Api. Идентификационният номер на играта на новата игра вече е записан в блокчейна, което означава, че вече не може да бъде променян или повлиян

6. Сървърът генерира функция за теглене (gameId, rsaSign). Например така:

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

7. Сървърът изпраща транзакция Invocation към интелигентния договор (излъчване InvocationTx). Транзакцията съдържа извикване на формирана функция за теглене (gameId, rsaSign):

RSA случаен на blockchain

Функцията съдържа идентификатор на играта нова игра и резултат от RSA подписване на уникален идентификатор с частен ключ. Резултатът от подписа е непроменен.

Какво означава това?

Взимаме същата стойност (идентификатор на играта) и прилагаме към нея метода за подпис RSA. Винаги ще получаваме един и същ резултат. Ето как работи алгоритъмът RSA. Крайното число не може да бъде манипулирано, тъй като идентификаторът на играта и резултатът от прилагането на RSA не са известни. Избирането на номер също е безсмислено.

8. Blockchain приема транзакцията. Той изпълнява функцията за теглене (gameId, rsaSign)

9. Вътре във функцията за оттегляне се извършва оттегляне Функции GenerateRandInt (gameId, rsaSign). Това е генератор на произволни числа

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

ред - и има произволно число.

Първо се взема низът, който е резултат от RSA подписа идентификатор на играта частен ключ (rsaSign). След това се хешира с SHA-256 (sha256(rsaSign)).

Не можем да предвидим резултата от подписа и последващото хеширане. Следователно е невъзможно да се повлияе на генерирането на произволно число. За да получите число в определен диапазон (например от 1 до 100), използвайте функцията за преобразуване toInt и %100 (подобно на моден).

В началото на статията споменахме функцията rsaVerify(), което ви позволява да проверите валидността на RSA подпис с помощта на частен ключ спрямо публичен. Ето частта GenerateRandInt(gameId,rsaSign):

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

Публичният ключ RSAPUBLIC и низът rsaSign се предават на входа. Подписът се проверява за валидност. Номерът се генерира, ако проверката е успешна. В противен случай системата счита, че подписът не е валиден (Невалиден RSA подпис).

Сървърът трябва да подпише идентификатора на играта с частен ключ и да изпрати валиден Rsa подпис в рамките на 2880 блока. Параметърът се конфигурира при внедряването на интелигентния договор. Ако нищо не се случи в рамките на определеното време, потребителят печели. В този случай наградата трябва да бъде изпратена на вашия адрес сами. Оказва се, че „не е изгодно за сървъра да мами“, защото това води до загуба. По-долу е даден пример.

RSA случаен на blockchain

Потребителят играе Казва Roller. Избрах 2 от 6-те страни на куба, залогът е 14 ВЪЛНИ. Ако сървърът не изпрати валиден RSA подпис към интелигентния договор в рамките на определеното време (2880 блока), потребителят ще вземе 34.44 WAVES.

За генериране на числа в игрите ние използваме оракул – външна, неблокчейн система. Сървърът извършва RSA подпис на идентификатора на играта. Интелигентният договор проверява валидността на подписа и определя победителя. Ако сървърът не изпрати нищо, тогава потребителят автоматично печели.

Това е честен метод за генериране, тъй като манипулацията е технически невъзможна. Всички игри на Tradisys работят на базата на описания алгоритъм. Ето как работят блокчейн игрите. Всичко е прозрачно и проверимо. Няма аналози на такава система в нито една друга блокчейн. Това е доста случайно.

Източник: www.habr.com

Добавяне на нов коментар