Асуудал бий - төвлөрсөн бус сүлжээнд санамсаргүй тоо үүсгэх нь хэцүү байдаг. Бараг бүх блокчэйн ийм асуудалтай тулгарсан. Үнэн хэрэгтээ хэрэглэгчдийн хооронд итгэлцэл байхгүй сүлжээнд маргаангүй санамсаргүй тоог бий болгох нь олон асуудлыг шийддэг.
Энэ нийтлэлд бид жишээ болгон тоглоом ашиглан асуудлыг хэрхэн шийдэж чадсаныг танд хэлэх болно. Тэдний эхнийх нь байсан
Бид эхний ээлжинд блокчэйний мэдээлэлд тулгуурлан тоо гаргахаар төлөвлөж байсан. Гэсэн хэдий ч дараа нь тодорхой болсон: дугаарыг удирдаж болно, энэ нь шийдэл нь тохиромжгүй гэсэн үг юм.
Бид тойрон гарах арга замыг олсон: commit-expand схемийг ашигла. Сервер 1-ээс 5 хүртэлх тоог тааж, давс нэмээд үр дүнг ашиглан хэш хийсэн
Тоглогч бооцоо тавьсан бөгөөд сервер нь далд дугаар болон "давс"-ыг ухаалаг гэрээ рүү илгээсэн. Энгийнээр хэлэхэд тэр хөзрүүдийг илчилсэн. Үүний дараа сервер тоонуудыг шалгаад хэрэглэгч хожсон уу, хожигдсон уу гэдгийг шийдэв.
Хэрэв сервер баталгаажуулахын тулд дугаар эсвэл "давс" илгээгээгүй бол хэрэглэгч ялсан. Энэ тохиолдолд тоглоом бүрийн хувьд ухаалаг гэрээг урьдчилан байрлуулж, түүнд боломжит ялалтыг оруулах шаардлагатай байв. Энэ нь эвгүй, цаг хугацаа их шаарддаг, үнэтэй байсан. Тэр үед өөр аюулгүй шийдэл байгаагүй.
Саяхан Tradisys баг Waves протоколд функц нэмэхийг санал болгов rsaVerify(). Энэ нь нийтийн болон хувийн түлхүүр дээр үндэслэн RSA гарын үсгийн хүчинтэй эсэхийг шалгадаг. Үүний үр дүнд функц нэмэгдсэн.
Бид гурван тоглоом боловсруулсан:
Ride on Waves ашиглан санамсаргүй тоо үүсгэхийг жишээ болгон авч үзье. Ухаалаг гэрээг олж болно
Таб руу очно уу Script мөн сонгоно уу Эмхэтгэсэн. Та ухаалаг гэрээний кодыг (скрипт гэх мэт) харах болно.
Ухаалаг гэрээний код нь олон тооны функцуудыг агуулдаг. @Callable гэж тэмдэглэгдсэн хүмүүсийг ашиглан эхлүүлж болно Дуудлага хийх гүйлгээ. Бид хоёр функцийг сонирхож байна: бооцоо и буцах:
- func бооцоо (тоглогчийн сонголт)
- функцийг татах(тоглоомын дугаар, rsaSign)
1. Хэрэглэгч сегментийн урт болон бооцооны хэмжээг сонгоно.
2. Үйлчлүүлэгч нь бооцооны функцийг үүсгэдэг. Дээрх зургийн хувьд ийм байх болно бооцоо("50").
3. Үйлчлүүлэгч Ухаалаг гэрээний хаяг руу Invocation гүйлгээг илгээдэг (InvocationTx нэвтрүүлэг). Гүйлгээ нь дуудлагын параметр болгон бооцооны функцийг агуулдаг. Энэ нь Дуудлага гүйлгээ нь ухаалаг гэрээн дээрх бооцооны функцийг (сонголт: Мөр) гүйцэтгэхийг өдөөдөг гэсэн үг юм.
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)
- Нийтийн түлхүүр
- Боломжит ялалт (тоглогчийн бооцооноос хамаарч)
Блокчэйн дэх өгөгдлийн бичлэг иймэрхүү харагдаж байна (түлхүүр утга):
{
"type": "string",
"value": "03WON_0283_448t8Jn9P3717UnXFEVD5VWjfeGE5gBNeWg58H2aJeQEgJ_06574069_09116020000_0229",
"key": "2GKTX6NLTgUrE4iy9HtpSSHpZ3G8W4cMfdjyvvnc21dx"
}
"Түлхүүр" (түлхүүр) - тоглоомын ID шинэ тоглоом. Үлдсэн өгөгдлийг "утга" талбарын мөрөнд оруулсан болно. Эдгээр оруулгууд нь таб дээр хадгалагдана Өгөгдөл ухаалаг гэрээ:
5. Сервер ухаалаг гэрээг "харж" блокчейн Api ашиглан илгээсэн гүйлгээг (шинэ тоглоом) олдог. Шинэ тоглоомын Тоглоомын ID нь блокчэйнд аль хэдийн бичигдсэн байгаа бөгөөд энэ нь цаашид өөрчлөх, нөлөөлөх боломжгүй гэсэн үг юм.
6. Сервер нь буцаах функцийг (gameId, rsaSign) үүсгэдэг. Жишээлбэл, иймэрхүү:
withdraw ("FwsuaaShC6DMWdSWQ5osGWtYkVbTEZrsnxqDbVx5oUpq", "base64:Gy69dKdmXUEsAmUrpoWxDLTQOGj5/qO8COA+QjyPVYTAjxXYvEESJbSiCSBRRCOAliqCWwaS161nWqoTL/TltiIvw3nKyd4RJIBNSIgEWGM1tEtNwwnRwSVHs7ToNfZ2Dvk/GgPUqLFDSjnRQpTHdHUPj9mQ8erWw0r6cJXrzfcagKg3yY/0wJ6AyIrflR35mUCK4cO7KumdvC9Mx0hr/ojlHhN732nuG8ps4CUlRw3CkNjNIajBUlyKQwpBKmmiy3yJa/QM5PLxqdppmfFS9y0sxgSlfLOgZ51xRDYuS8NViOA7c1JssH48ZtDbBT5yqzRJXs3RnmZcMDr/q0x6Bg==")
7. Сервер нь Ухаалаг гэрээ рүү (InvocationTx нэвтрүүлэг) Invocation гүйлгээг илгээдэг. Гүйлгээ нь үүссэн татах функц (gameId, rsaSign) руу залгасан дуудлагыг агуулна.
Функц нь агуулдаг тоглоомын ID шинэ тоглоом ба хувийн түлхүүр бүхий өвөрмөц танигчтай RSA гарын үсэг зурсны үр дүн. Гарын үсгийн үр дүн өөрчлөгдөөгүй.
Энэ нь юу гэсэн үг вэ?
Бид ижил утгыг (тоглоомын id) авч, түүнд RSA гарын үсгийн аргыг ашигладаг. Бид үргэлж ижил үр дүнд хүрэх болно. RSA алгоритм ингэж ажилладаг. Тоглоомын id болон RSA-г хэрэглэсний үр дүн тодорхойгүй тул эцсийн тоог өөрчлөх боломжгүй. Тоо сонгох нь бас утгагүй юм.
8. Блокчейн нь гүйлгээг хүлээн зөвшөөрдөг. Энэ нь буцаах функцийг ажиллуулдаг (gameId, rsaSign)
9. Татах функцийн дотор татан авалт үүсдэг GenerateRandInt функцууд (тоглоомын дугаар, 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 гарын үсгийн үр дүн болох мөрийг авдаг тоглоомын ID хувийн түлхүүр (rsaSign). Дараа нь SHA-256 (sha256(rsaSign)).
Гарын үсэг болон дараагийн хэшний үр дүнг бид урьдчилан таамаглах боломжгүй. Тиймээс санамсаргүй тоо үүсгэхэд нөлөөлөх боломжгүй юм. Тодорхой мужид (жишээ нь 1-ээс 100 хүртэл) тоо авахын тулд toInt хувиргах функц болон % 100 (үүнтэй төстэй) ашиглана уу.
Өгүүллийн эхэнд бид функцийг дурдсан rsaVerify(), энэ нь RSA гарын үсгийн хүчинтэй эсэхийг хувийн түлхүүр ашиглан нийтийн гарын үсгийн эсрэг шалгах боломжийг олгодог. Энд GenerateRandInt(gameId,rsaSign) хэсэг байна:
rsaVerify (SHA256, toBytes(gameId), rsaSign, RSAPUBLIC)
RSAPUBLIC нийтийн түлхүүр болон rsaSign мөрийг оролт руу дамжуулдаг. Гарын үсэг хүчинтэй эсэхийг шалгана. Шалгалт амжилттай болсон тохиолдолд дугаар үүсгэгдэнэ. Үгүй бол систем гарын үсгийг хүчингүй гэж үздэг (RSA гарын үсэг хүчингүй).
Сервер нь хувийн түлхүүрээр тоглоомын ID-д гарын үсэг зурж, 2880 блок дотор хүчинтэй Rsa гарын үсэг илгээх ёстой. Ухаалаг гэрээг байршуулах үед параметрийг тохируулна. Хэрэв заасан хугацаанд юу ч болоогүй бол хэрэглэгч ялна. Энэ тохиолдолд шагналыг өөрийн хаягаар өөрөө илгээх ёстой. Энэ нь алдагдалд хүргэдэг тул "серверийг хуурах нь ашиггүй" болж байна. Доорх жишээг үзүүлэв.
Хэрэглэгч тоглож байна
Тоглоомонд тоо үүсгэхийн тулд бид oracle ашигладаг - гадаад, блокчлонгүй систем. Сервер нь тоглоомын ID-н RSA гарын үсэг зурдаг. Ухаалаг гэрээ нь гарын үсгийн хүчинтэй эсэхийг шалгаж, ялагчийг тодорхойлдог. Хэрэв сервер юу ч илгээгээгүй бол хэрэглэгч автоматаар ялна.
Техникийн хувьд манипуляци хийх боломжгүй тул энэ бол шударга үеийн арга юм. Бүх Tradisys тоглоомууд тайлбарласан алгоритм дээр тулгуурлан ажилладаг. Блокчейн тоглоомууд ингэж ажилладаг. Бүх зүйл ил тод, шалгах боломжтой. Бусад блокчэйнд ийм системийн аналог байхгүй. Энэ бол шударга санамсаргүй тохиолдол юм.
Эх сурвалж: www.habr.com