Ir problÄma ā decentralizÄtÄ tÄ«klÄ ir grÅ«ti Ä£enerÄt nejauÅ”u skaitli. GandrÄ«z visas blokÄ·Ädes jau ir ar to saskÄruÅ”Äs. PatieÅ”Äm, tÄ«klos, kur starp lietotÄjiem nav uzticÄ«bas, nenoliedzama nejauÅ”a skaitļa izveidoÅ”ana atrisina daudzas problÄmas.
Å ajÄ rakstÄ mÄs jums pastÄstÄ«sim, kÄ mums izdevÄs atrisinÄt problÄmu, izmantojot spÄles kÄ piemÄru. Pirmais no tiem bija
SÄkotnÄji mÄs plÄnojÄm Ä£enerÄt numuru, pamatojoties uz informÄciju no blokÄ·Ädes. TomÄr tad kļuva skaidrs: ar numuru var manipulÄt, kas nozÄ«mÄ, ka risinÄjums nav piemÄrots.
MÄs izdomÄjÄm risinÄjumu: izmantojiet commit-expand shÄmu. Serveris uzminÄja skaitli no 1 lÄ«dz 5, pievienoja tam sÄli un pÄc tam sajauca rezultÄtu, izmantojot
SpÄlÄtÄjs izdarÄ«ja likmi, un serveris nosÅ«tÄ«ja slÄpto numuru un āsÄliā viedajam lÄ«gumam. VienkÄrÅ”i sakot, viÅÅ” atklÄja kÄrtis. PÄc tam serveris pÄrbaudÄ«ja skaitļus un nolÄma, vai lietotÄjs uzvarÄja vai zaudÄja.
Ja serveris verifikÄcijai nenosÅ«tÄ«ja numuru vai āsÄliā, lietotÄjs uzvarÄja. Å ajÄ gadÄ«jumÄ katrai spÄlei bija nepiecieÅ”ams iepriekÅ” izveidot viedo lÄ«gumu un iekļaut tajÄ iespÄjamos laimestus. Tas izrÄdÄ«jÄs neÄrti, laikietilpÄ«gi un dÄrgi. Toreiz cita droÅ”a risinÄjuma nebija.
Nesen Tradisys komanda ierosinÄja pievienot funkciju Waves protokolam rsaVerify(). TÄ pÄrbauda RSA paraksta derÄ«gumu, pamatojoties uz publisko un privÄto atslÄgu. RezultÄtÄ funkcija tika pievienota.
MÄs esam izstrÄdÄjuÅ”i trÄ«s spÄles:
ApskatÄ«sim nejauÅ”a skaitļa Ä£enerÄÅ”anu, kÄ piemÄru izmantojot Ride on Waves. Viedo lÄ«gumu var atrast
Atveriet cilni ScenÄrijs un izvÄlieties DekompilÄts. JÅ«s redzÄsit viedÄ lÄ«guma kodu (aka skriptu).
ViedÄ lÄ«guma kods satur funkciju kopu. Tos, kas atzÄ«mÄti kÄ @Callable, var palaist, izmantojot Izsaukuma darÄ«jumi. MÅ«s interesÄ divas funkcijas: derÄt Šø atsaukt:
- Func likme (spÄlÄtÄja izvÄle)
- funkcija atsaukt(gameId,rsaSign)
1. LietotÄjs izvÄlas segmenta garumu un likmes lielumu.
2. Klients izveido likmes funkciju. IepriekÅ” redzamajam attÄlam tas bÅ«tu likme ("50").
3. Klients nosÅ«ta Invocation transakciju uz viedÄ lÄ«guma adresi (broadcast InvocationTx). DarÄ«jums satur likmes funkciju kÄ izsaukuma parametru. Tas nozÄ«mÄ, ka izsaukÅ”anas darÄ«jums aktivizÄ likmes funkcijas (izvÄle: virkne) izpildi viedajÄ lÄ«gumÄ.
4. Apsveriet likmes funkciju:
@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 ieraksta jaunu spÄli viedÄ lÄ«guma stÄvoklÄ«. Proti:
- UnikÄls identifikators jaunai spÄlei (spÄles ID)
- SpÄles stÄvoklis = IESNIEGTS
- SpÄlÄtÄja izvÄle (segmenta garums 50)
- PubliskÄ atslÄga
- PotenciÄlie laimesti (atkarÄ«bÄ no spÄlÄtÄja likmes)
Å Ädi izskatÄs datu ieraksts blokÄ·ÄdÄ (atslÄgas vÄrtÄ«ba):
{
"type": "string",
"value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229",
"key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx"
}
"AtslÄga" (atslÄga) - spÄles id jauna spÄle. PÄrÄjie dati ir ietverti lauka āvÄrtÄ«baā rindÄ. Å ie ieraksti tiek saglabÄti cilnÄ Datums viedais lÄ«gums:
5. Serveris āapskatÄsā viedo lÄ«gumu un, izmantojot blokÄ·Ädes Api, atrod nosÅ«tÄ«to transakciju (jaunu spÄli). JaunÄs spÄles spÄles ID jau ir ierakstÄ«ts blokÄ·ÄdÄ, kas nozÄ«mÄ, ka to vairs nevar mainÄ«t vai ietekmÄt
6. Serveris Ä£enerÄ atsaukÅ”anas funkciju (gameId, rsaSign). PiemÄram, Å”Ädi:
withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==")
7. Serveris nosÅ«ta Invocation transakciju viedajam lÄ«gumam (broadcast InvocationTx). DarÄ«jums satur izsaukumu uz izveidoto izÅemÅ”anas funkciju (gameId, rsaSign):
Funkcija satur spÄles id jauna spÄle un RSA unikÄlÄ identifikatora parakstÄ«Å”anas rezultÄts ar privÄto atslÄgu. Paraksta rezultÄts ir nemainÄ«gs.
Ko tas nozÄ«mÄ?
MÄs Åemam to paÅ”u vÄrtÄ«bu (spÄles ID) un piemÄrojam tai RSA paraksta metodi. MÄs vienmÄr iegÅ«sim to paÅ”u rezultÄtu. Å Ädi darbojas RSA algoritms. Ar galÄ«go numuru nevar manipulÄt, jo spÄles ID un RSA piemÄroÅ”anas rezultÄts nav zinÄms. ArÄ« skaitļa izvÄle ir bezjÄdzÄ«ga.
8. Blockchain pieÅem darÄ«jumu. Tas palaiž izÅemÅ”anas funkciju (gameId, rsaSign)
9. IzÅemÅ”anas funkcijas ietvaros notiek izÅemÅ”ana GenerateRandInt funkcijas (gameId, rsaSign). Å is ir nejauÅ”o skaitļu Ä£enerators
# @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")
}
rinda - un ir nejauŔs skaitlis.
PirmkÄrt, tiek Åemta virkne, kas ir RSA paraksta rezultÄts spÄles id privÄtÄ atslÄga (rsaSign). PÄc tam jaukta ar SHA-256 (sha256 (rsaSign)).
MÄs nevaram paredzÄt parakstÄ«Å”anas un turpmÄkÄs jaukÅ”anas iznÄkumu. TÄpÄc nav iespÄjams ietekmÄt nejauÅ”a skaitļa Ä£enerÄÅ”anu. Lai iegÅ«tu skaitli noteiktÄ diapazonÄ (piemÄram, no 1 lÄ«dz 100), izmantojiet konvertÄÅ”anas funkciju toInt un %100 (lÄ«dzÄ«gi kÄ
Raksta sÄkumÄ mÄs minÄjÄm funkciju rsaVerify(), kas ļauj pÄrbaudÄ«t RSA paraksta derÄ«gumu, izmantojot privÄto atslÄgu, salÄ«dzinot ar publisko atslÄgu. Å eit ir daļa GenerateRandInt(gameId,rsaSign):
rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
PubliskÄ atslÄga RSAPUBLIC un rsaSign virkne tiek nodota ievadei. Tiek pÄrbaudÄ«ts paraksta derÄ«gums. Numurs tiek Ä£enerÄts, ja pÄrbaude ir veiksmÄ«ga. PretÄjÄ gadÄ«jumÄ sistÄma uzskata, ka paraksts nav derÄ«gs (NederÄ«gs RSA paraksts).
Serverim jÄparaksta spÄles ID ar privÄto atslÄgu un jÄnosÅ«ta derÄ«gs Rsa paraksts 2880 bloku robežÄs. Parametrs tiek konfigurÄts, izvietojot viedo lÄ«gumu. Ja nekas nenotiek atvÄlÄtajÄ laikÄ, lietotÄjs uzvar. Å ajÄ gadÄ«jumÄ balva paÅ”am jÄnosÅ«ta uz savu adresi. IzrÄdÄs, ka āserverim nav izdevÄ«gi krÄptiesā, jo tas noved pie zaudÄjumiem. ZemÄk ir piemÄrs.
LietotÄjs spÄlÄ
Lai Ä£enerÄtu skaitļus spÄlÄs, mÄs izmantojam orÄkulu - ÄrÄju, bez blokÄ·Ädes sistÄmu. Serveris veic spÄles ID RSA parakstu. Viedais lÄ«gums pÄrbauda paraksta derÄ«gumu un nosaka uzvarÄtÄju. Ja serveris neko nesÅ«ta, lietotÄjs automÄtiski uzvar.
TÄ ir godÄ«ga Ä£enerÄÅ”anas metode, jo manipulÄcija tehniski nav iespÄjama. Visas Tradisys spÄles darbojas, pamatojoties uz aprakstÄ«to algoritmu. Å Ädi darbojas blokÄ·Ädes spÄles. Viss ir caurspÄ«dÄ«gs un pÄrbaudÄms. Å Ädai sistÄmai nav analogu nevienÄ citÄ blokÄ·ÄdÄ. Å Ä« ir godÄ«ga nejauŔība.
Avots: www.habr.com