RSA random sa blockchain

May problema - mahirap bumuo ng random na numero sa isang desentralisadong network. Halos lahat ng blockchain ay nakatagpo na nito. Sa katunayan, sa mga network kung saan walang tiwala sa pagitan ng mga gumagamit, ang paglikha ng isang hindi maikakaila na random na numero ay malulutas ang maraming mga problema.

Sa artikulong ito, sasabihin namin sa iyo kung paano namin nalutas ang problema gamit ang mga laro bilang isang halimbawa. Ang una sa kanila ay Waves Xmas Tree. Para sa pag-unlad, kailangan namin ng isang random na generator ng numero.

RSA random sa blockchain

Sa una, nagplano kaming bumuo ng isang numero batay sa impormasyon mula sa blockchain. Gayunpaman, pagkatapos ay naging malinaw: ang numero ay maaaring manipulahin, na nangangahulugang ang solusyon ay hindi angkop.

Nakagawa kami ng workaround: gamitin ang commit-expand scheme. Nahulaan ng server ang isang numero mula 1 hanggang 5, nagdagdag ng asin dito, at pagkatapos ay na-hash ang resulta gamit Mga function ng Keccak. Ang server ay nag-deploy ng matalinong kontrata kasama ang na-save nang numero nang maaga. Lumalabas na ang laro ay nahulaan ng user ang numerong itinago ng hash.

Naglagay ang manlalaro ng taya, at ipinadala ng server ang nakatagong numero at β€œasin” sa matalinong kontrata. Sa simpleng salita, inihayag niya ang mga kard. Pagkatapos nito, sinuri ng server ang mga numero at nagpasya kung nanalo o natalo ang user.

Kung hindi nagpadala ang server ng numero o β€œasin” para sa pag-verify, nanalo ang user. Sa kasong ito, para sa bawat laro ay kinakailangan na mag-deploy ng isang matalinong kontrata nang maaga at isama ang mga potensyal na panalo dito. Ito ay naging hindi maginhawa, matagal at mahal. Sa oras na iyon ay walang ibang ligtas na solusyon.

Kamakailan, iminungkahi ng Tradisys team ang pagdaragdag ng function sa Waves protocol rsaVerify(). Sinusuri nito ang bisa ng lagda ng RSA batay sa pampubliko at pribadong susi. Bilang resulta, idinagdag ang tampok.

Nakabuo kami ng tatlong laro: Roller Dice, Coin Flip ΠΈ Sumakay Sa Mga Alon. Ang bawat isa ay nagpapatupad ng random na teknolohiya ng numero. Alamin natin kung paano ito gumagana.

RSA random sa blockchain

Tingnan natin ang pagbuo ng random na numero gamit ang Ride on Waves bilang isang halimbawa. Ang matalinong kontrata ay matatagpuan dito.

Pumunta sa tab Iskrip at piliin Na-decompile. Makikita mo ang smart contract code (aka script).

RSA random sa blockchain

Ang smart contract code ay naglalaman ng isang hanay ng mga function. Ang mga minarkahan bilang @Callable ay maaaring ilunsad gamit Mga transaksyon sa panawagan. Kami ay interesado sa dalawang pag-andar: tumaya ΠΈ bawiin:

  • func bet (playerChoice)
  • function withdraw(gameId,rsaSign)

1. Pinipili ng user ang haba ng segment at ang laki ng taya.

RSA random sa blockchain

2. Lumilikha ang kliyente ng function ng taya. Para sa larawan sa itaas ito ay magiging taya("50").

3. Nagpapadala ang kliyente ng transaksyon sa Invocation sa smart contract address (broadcast InvocationTx). Ang transaksyon ay naglalaman ng function ng taya bilang isang parameter ng tawag. Nangangahulugan ito na ang transaksyon ng Invocation ay nagti-trigger ng pagpapatupad ng function ng taya (pagpipilian: String) sa matalinong kontrata.

RSA random sa blockchain

4. Isaalang-alang ang function ng taya:

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

Ang function ay nagsusulat ng isang bagong laro sa estado ng matalinong kontrata. Namely:

  • Natatanging identifier para sa isang bagong laro (game id)
  • Katayuan ng laro = NAISUMITE
  • Pinili ng manlalaro (haba ng segment 50)
  • Pampublikong susi
  • Mga potensyal na panalo (depende sa taya ng manlalaro)

RSA random sa blockchain

Ito ang hitsura ng isang talaan ng data sa blockchain (key-value):

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

"Susi" (susi) - id ng laro bagong laro. Ang natitirang data ay nakapaloob sa linya ng field na "halaga". Ang mga entry na ito ay naka-imbak sa tab data matalinong kontrata:

RSA random sa blockchain

RSA random sa blockchain

5. Ang server ay "tumingin" sa matalinong kontrata at hinahanap ang ipinadalang transaksyon (bagong laro) gamit ang blockchain Api. Ang Game id ng bagong laro ay naitala na sa blockchain, na nangangahulugang hindi na ito mababago o maimpluwensyahan

6. Ang server ay bumubuo ng isang withdraw function (gameId, rsaSign). Halimbawa, tulad nito:

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

7. Nagpapadala ang server ng transaksyon sa Invocation sa smart contract (broadcast InvocationTx). Ang transaksyon ay naglalaman ng isang tawag sa nabuong withdraw function (gameId, rsaSign):

RSA random sa blockchain

Naglalaman ang function id ng laro bagong laro at ang resulta ng RSA signing ng isang natatanging identifier na may pribadong key. Ang resulta ng lagda ay hindi nagbabago.

Ano ang ibig sabihin nito?

Kinukuha namin ang parehong halaga (game id) at inilapat ang RSA signature method dito. Palagi kaming makakakuha ng parehong resulta. Ito ay kung paano gumagana ang RSA algorithm. Ang huling numero ay hindi maaaring manipulahin, dahil ang laro id at ang resulta ng paglalapat ng RSA ay hindi alam. Walang kabuluhan din ang pagpili ng numero.

8. Tinatanggap ng Blockchain ang transaksyon. Pinapatakbo nito ang withdraw function (gameId, rsaSign)

9. Sa loob ng withdraw function, nangyayari ang withdrawal Mga function ng GenerateRandInt (gameId, rsaSign). Ito ay isang random na generator ng numero

# @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 - at mayroong isang random na numero.

Una, kinuha ang string, na resulta ng lagda ng RSA id ng laro pribadong susi (rsaSign). Pagkatapos ay na-hash gamit ang SHA-256 (sha256(rsaSign)).

Hindi namin mahuhulaan ang kinalabasan ng lagda at kasunod na pag-hash. Samakatuwid, imposibleng maimpluwensyahan ang pagbuo ng isang random na numero. Upang makakuha ng numero sa isang partikular na hanay (halimbawa, mula 1 hanggang 100), gamitin ang toInt conversion function at %100 (katulad ng mod).

Sa simula ng artikulo ay binanggit namin ang function rsaVerify(), na nagbibigay-daan sa iyong suriin ang bisa ng isang RSA signature na may pribadong key laban sa isang pampubliko. Narito ang bahagi ng GenerateRandInt(gameId,rsaSign):

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

Ang pampublikong key na RSAPUBLIC at ang rsaSign string ay ipinapasa sa input. Ang pirma ay sinusuri para sa bisa. Ang numero ay nabuo kung ang tseke ay matagumpay. Kung hindi, isinasaalang-alang ng system na ang lagda ay hindi wasto (Invalid RSA signature).

Dapat lagdaan ng server ang game id gamit ang pribadong key at magpadala ng wastong Rsa signature sa loob ng 2880 blocks. Naka-configure ang parameter kapag nagde-deploy ng smart contract. Kung walang mangyayari sa loob ng inilaang oras, panalo ang user. Sa kasong ito, ang premyo ay dapat na ipadala sa iyong address mismo. Ito ay lumalabas na ito ay "hindi kumikita para sa server na manloko", dahil ito ay humahantong sa pagkawala. Nasa ibaba ang isang halimbawa.

RSA random sa blockchain

Naglalaro ang gumagamit Roller Dice. Pinili ko ang 2 sa 6 na gilid ng kubo, ang taya ay 14 WAVES. Kung hindi nagpadala ang server ng wastong RSA signature sa smart contract sa loob ng tinukoy na oras (2880 blocks), kukuha ang user ng 34.44 WAVES.

Upang makabuo ng mga numero sa mga laro, gumagamit kami ng oracle - isang panlabas, hindi blockchain system. Nagsasagawa ang server ng RSA signature ng game id. Sinusuri ng matalinong kontrata ang bisa ng lagda at tinutukoy ang nanalo. Kung ang server ay hindi nagpapadala ng anuman, ang gumagamit ay awtomatikong mananalo.

Ito ay isang matapat na paraan ng henerasyon, dahil ang pagmamanipula ay teknikal na imposible. Gumagana ang lahat ng laro ng Tradisys batay sa inilarawang algorithm. Ganito gumagana ang mga larong blockchain. Lahat ay transparent at nabe-verify. Walang mga analogue ng naturang sistema sa anumang iba pang blockchain. Ito ay isang patas na random.

Pinagmulan: www.habr.com

Magdagdag ng komento