tx · F6RpxQT5HqcMhmoYwPTaxvfC5AdZ9JNwsdsAU6tCBuGR

3MqtTwie8XKCcUcntgFAFYnfLEnffezju4Y:  -0.01500000 Waves

2019.08.09 18:48 [623645] smart account 3MqtTwie8XKCcUcntgFAFYnfLEnffezju4Y > SELF 0.00000000 Waves

{ "type": 13, "id": "F6RpxQT5HqcMhmoYwPTaxvfC5AdZ9JNwsdsAU6tCBuGR", "fee": 1500000, "feeAssetId": null, "timestamp": 1565365776179, "version": 1, "sender": "3MqtTwie8XKCcUcntgFAFYnfLEnffezju4Y", "senderPublicKey": "Gf4eU8JJaQziR7AfnST6tmzhUgFmeKavkwyoceen3PK1", "proofs": [ "32xqDZBvJ4teVG7R7aAh98BiT62Pdxzijb9ZQpPqu7BNWMUFhDSdkKEa4QTLa4DJLgaFczUG7iW3b6tfy2f7KUmE" ], "script": "base64:AAIDAAAAAAAAAAAAAAAaAAAAAAlSU0FQVUJMSUMJAAJbAAAAAQIAAAGPYmFzZTY0Ok1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBcWxBaUFOU21CcERIWUtQOXNLZ2VOL2wxYkFiMjhnL3RHbGdEa3dUNUZpTU40WDNwd2R2ZHhFN212U1I4LzQxZFU5cng0akcrNnRacGIxVUxWRFBzNDMxdFIySVJhVFh3NUNqK0FjMnZoTCs1SmFtQ2VyR0QxVVcrYmgvRUdRdHhvOFczWUxEcm9mWEI1UUhKeDRQa3oyS2dmK29TL0M4aEh1Qi9VNGtyTzc2VTA1MDdHVGpaUFA5a1JRMHVMU01lcVFYdDh3WFMrbk1wNXdhanF4UHBETE1hU1JFZ3NLd3YvQUVrUDRkenBUWWJpa0xCWWw0cXRkSnNEODRITEZTa2l3ZDNCaGNPclBqb0lZbUx4UXVCRDVUSU1LVEtEM3NkWmdhWTlyc3lxeDNBMDBpbm55eEQ2enAzYjRnRnBVT1g4SnhLWmRFQzJteUVxbGVOZ2c3R3p3SURBUUFCAAAAAAZTRVJWRVIJAQAAABxAZXh0clVzZXIoYWRkcmVzc0Zyb21TdHJpbmcpAAAAAQIAAAAjM05DaUcyOExtV3lUaWdXRzEzRTVRbnZkSEJzWkZZWFNTMmoAAAAAB1dBVkVMRVQJAABoAAAAAgkAAGgAAAACAAAAAAAAAABkAAAAAAAAAAPoAAAAAAAAAAPoAAAAABBTRVNTSU9OSURGSVhTSVpFAAAAAAAAAAAsAAAAAA5SQU5EQ1lDTEVQUklDRQkAAGkAAAACCQAAaAAAAAIAAAAAAAAAAAUFAAAAB1dBVkVMRVQAAAAAAAAAA+gAAAAAEE1BWFJBTkRTUEVSQ1lDTEUAAAAAAAAAAA4AAAAACVNUQVRFSU5JVAIAAAAESU5JVAAAAAAIREFUQURPTkUCAAAABVJFQURZAAAAAA1TVEFURUZJTklTSEVEAgAAAAhGSU5JU0hFRAAAAAAISWR4U3RhdGUAAAAAAAAAAAAAAAAAD0lkeE9yZ2FuaXplclB1YgAAAAAAAAAAAQAAAAALSWR4UmFuZEZyb20AAAAAAAAAAAIAAAAACUlkeFJhbmRUbwAAAAAAAAAAAwAAAAANSWR4UmFuZHND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NTgJAAGkAAAAAQUAAAAIcmFuZEZyb20JAAGkAAAAAQUAAAAGcmFuZFRvBQAAAA1yYW5kc0NvdW50U3RyBQAAAA1yYW5kc0NvdW50U3RyCQABpAAAAAEFAAAADWRhdGFLZXlzQ291bnQCAAAABG51bGwCAAAAATACAAAAATACAAAAATECAAAAATACAAAAATECAAAAAAkBAAAADFNjcmlwdFJlc3VsdAAAAAIJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAACXNlc3Npb25JZAUAAAAJaW5pdFN0YXRlBQAAAANuaWwJAQAAAAtUcmFuc2ZlclNldAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAGU0VSVkVSBQAAAAhyYW5kc1BtdAUAAAAEdW5pdAUAAAADbmlsAAAAAWkBAAAABXJlYWR5AAAAAQAAAAlzZXNzaW9uSWQEAAAADmRyYXdQYXJhbXNMaXN0CQEAAAATZXh0cmFjdEdhbWVEYXRhTGlzdAAAAAEFAAAACXNlc3Npb25JZAQAAAAJZHJhd1N0YXRlCQABkQAAAAIFAAAADmRyYXdQYXJhbXNMaXN0BQAAAAhJZHhTdGF0ZQQAAAARb3JnYW5pemVyUHViS2V5NTgJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QFAAAAD0lkeE9yZ2FuaXplclB1YgQAAAANcmFuZHNDb3VudFN0cgkAAZEAAAACBQAAAA5kcmF3UGFyYW1zTGlzdAUAAAANSWR4UmFuZHNDb3VudAQAAAATcmVtYWluUmFuZHNDb3VudFN0cgkAAZEAAAACBQAAAA5kcmF3UGFyYW1zTGlzdAUAAAATSWR4UmVtYWluUmFuZHNDb3VudAQAAAAHZnJvbVN0cgkAAZEAAAACBQAAAA5kcmF3UGFyYW1zTGlzdAUAAAALSWR4UmFuZEZyb20EAAAABXRvU3RyCQABkQAAAAIFAAAADmRyYXdQYXJhbXNMaXN0BQAAAAlJZHhSYW5kVG8EAAAADWRhdGFLZXlzQ291bnQJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QFAAAAEElkeERhdGFLZXlzQ291bnQEAAAAD29yZ2FuaXplclB1YktleQkAAlkAAAABBQAAABFvcmdhbml6ZXJQdWJLZXk1OAMJAQAAAAIhPQAAAAIFAAAACWRyYXdTdGF0ZQUAAAAJU1RBVEVJTklUCQAAAgAAAAEJAAEsAAAAAgUAAAAJc2Vzc2lvbklkAgAAAD4gZHJhdzogbW92aW5nIGludG8gUkVBRFkgc3RhdGUgaXMgYWxsb3dlZCBvbmx5IGZyb20gSU5JVCBzdGF0ZQMJAQAAAAIhPQAAAAIFAAAAD29yZ2FuaXplclB1YktleQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAEJAAEsAAAAAgUAAAAJc2Vzc2lvbklkAgAAADtkcmF3OiBtb3ZpbmcgaW50byBSRUFEWSBzdGF0ZSBpcyBhbGxvd2VkIGZvciBvcmdhbml6ZXIgb25seQQAAAAKcmVhZHlTdGF0ZQkBAAAAEmZvcm1hdFN0YXRlRGF0YVN0cgAAAA4FAAAACERBVEFET05FBQAAABFvcmdhbml6ZXJQdWJLZXk1OAUAAAAHZnJvbVN0cgUAAAAFdG9TdHIFAAAADXJhbmRzQ291bnRTdHIFAAAAE3JlbWFpblJhbmRzQ291bnRTdHIFAAAADWRhdGFLZXlzQ291bnQJAAJYAAAAAQgFAAAAAWkAAAANdHJhbnNhY3Rpb25JZAIAAAABMAIAAAABMAIAAAABMQIAAAABMAIAAAABMQIAAAAACQEAAAAIV3JpdGVTZXQAAAABCQAETAAAAAIJAQAAAAlEYXRhRW50cnkAAAACBQAAAAlzZXNzaW9uSWQFAAAACnJlYWR5U3RhdGUFAAAAA25pbAAAAAFpAQAAAAZyYW5kb20AAAACAAAACXNlc3Npb25JZAAAAAdyc2FTaWduBAAAAA5kcmF3UGFyYW1zTGlzdAkBAAAAE2V4dHJhY3RHYW1lRGF0YUxpc3QAAAABBQAAAAlzZXNzaW9uSWQEAAAACWRyYXdTdGF0ZQkAAZEAAAACBQAAAA5kcmF3UGFyYW1zTGlzdAUAAAAISWR4U3RhdGUEAAAAEW9yZ2FuaXplclB1YktleTU4CQABkQAAAAIFAAAADmRyYXdQYXJhbXNMaXN0BQAAAA9JZHhPcmdhbml6ZXJQdWIEAAAADXJhbmRzQ291bnRTdHIJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QFAAAADUlkeFJhbmRzQ291bnQEAAAAEHJlbWFpblJhbmRzQ291bnQJAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAA5kcmF3UGFyYW1zTGlzdAUAAAATSWR4UmVtYWluUmFuZHNDb3VudAQAAAAPbGFzdE9mZnNldEJ5dGVzCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QFAAAADUlkeExhc3RPZmZzZXQEAAAADGN1cnJSYW5kc1N0cgkAAZEAAAACBQAAAA5kcmF3UGFyYW1zTGlzdAUAAAAMSWR4Q3VyclJhbmRzBAAAAAdmcm9tU3RyCQABkQAAAAIFAAAADmRyYXdQYXJhbXNMaXN0BQAAAAtJZHhSYW5kRnJvbQQAAAAFdG9TdHIJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QFAAAACUlkeFJhbmRUbwQAAAAMZGF0YURvbmVUeElkCQABkQAAAAIFAAAADmRyYXdQYXJhbXNMaXN0BQAAAA9JZHhEYXRhRG9uZVR4SWQEAAAACHNsb3dJZHgxCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QAAAAAAAAAAAkEAAAACHNsb3dJZHgyCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QAAAAAAAAAAAoEAAAACGZhc3RJZHgxCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QAAAAAAAAAAAsEAAAACGZhc3RJZHgyCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QAAAAAAAAAAAwEAAAABGZyb20JAQAAAA1wYXJzZUludFZhbHVlAAAAAQUAAAAHZnJvbVN0cgQAAAACdG8JAQAAAA1wYXJzZUludFZhbHVlAAAAAQUAAAAFdG9TdHIEAAAAD29yZ2FuaXplclB1YktleQkAAlkAAAABBQAAABFvcmdhbml6ZXJQdWJLZXk1OAMJAQAAAAIhPQAAAAIFAAAACWRyYXdTdGF0ZQUAAAAIREFUQURPTkUJAAACAAAAAQkAASwAAAACBQAAAAlzZXNzaW9uSWQCAAAAOyBkcmF3OiBpdCBtdXN0IGJlIGluIFJFQURZIHN0YXRlIHRvIGdlbmVyYXRlIHJhbmRvbSBudW1iZXJzAwkBAAAAASEAAAABCQAB+AAAAAQFAAAABlNIQTI1NgkAAMsAAAACCQABmwAAAAEFAAAACXNlc3Npb25JZAkAAZsAAAABBQAAAAxkYXRhRG9uZVR4SWQFAAAAB3JzYVNpZ24FAAAACVJTQVBVQkxJQwkAAAIAAAABAgAAABVJbnZhbGlkIFJTQSBzaWduYXR1cmUEAAAAC3JhbmRHZW5JbmZvCQEAAAAMZ2VuZXJhdGVSYW5kAAAACwUAAAAJc2Vzc2lvbklkBQAAAARmcm9tBQAAAAJ0bwUAAAAHcnNhU2lnbgUAAAAMY3VyclJhbmRzU3RyBQAAABByZW1haW5SYW5kc0NvdW50BQAAAA9sYXN0T2Zmc2V0Qnl0ZXMFAAAACHNsb3dJZHgxBQAAAAhzbG93SWR4MgUAAAAIZmFzdElkeDEFAAAACGZhc3RJZHgyBAAAABZuZXdSZW1haW5SYW5kc0NvdW50U3RyCQABkQAAAAIFAAAAC3JhbmRHZW5JbmZvAAAAAAAAAAABBAAAAAhuZXdTdGF0ZQMJAAAAAAAAAgUAAAAWbmV3UmVtYWluUmFuZHNDb3VudFN0cgIAAAABMAUAAAANU1RBVEVGSU5JU0hFRAUAAAAIREFUQURPTkUJAQAAAAhXcml0ZVNldAAAAAEJAARMAAAAAgkBAAAACURhdGFFbnRyeQAAAAIFAAAACXNlc3Npb25JZAkBAAAAEmZvcm1hdFN0YXRlRGF0YVN0cgAAAA4FAAAACG5ld1N0YXRlBQAAABFvcmdhbml6ZXJQdWJLZXk1OAUAAAAHZnJvbVN0cgUAAAAFdG9TdHIFAAAADXJhbmRzQ291bnRTdHIFAAAAFm5ld1JlbWFpblJhbmRzQ291bnRTdHIJAAGRAAAAAgUAAAAOZHJhd1BhcmFtc0xpc3QFAAAAEElkeERhdGFLZXlzQ291bnQFAAAADGRhdGFEb25lVHhJZAkAAZEAAAACBQAAAAtyYW5kR2VuSW5mbwAAAAAAAAAAAgkAAZEAAAACBQAAAAtyYW5kR2VuSW5mbwAAAAAAAAAAAwkAAZEAAAACBQAAAAty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", "chainId": 84, "height": 623645, "spentComplexity": 0 } View: original | compacted Prev: E7kdGeKUvaWAQXHi33iKFajNzK6eyfsMWGXEjtUoJGi3 Next: DBLbhHFaizgYow4i1X3FTKK94mRRCXAeNZzpCxrTc2R9 Diff:
OldNewDifferences
3131
3232 let IdxRemainRandsCount = 5
3333
34-let IdxDataDoneTxId = 6
34+let IdxDataKeysCount = 6
3535
36-let IdxLastOffset = 7
36+let IdxDataDoneTxId = 7
3737
38-let IdxCurrRands = 8
38+let IdxLastOffset = 8
39+
40+let IdxCurrRands = 13
3941
4042 func abs (val) = if ((0 > val))
4143 then -(val)
4244 else val
4345
4446
45-func formatStateDataStr (drawState,organizerPubKey58,randFrom,randTo,randsCount,remainingRands,dataDoneTxId,lastOffset,randOrEmpty) = {
46- let fullStateStr = ((((((((((((((drawState + "_") + organizerPubKey58) + "_") + randFrom) + "_") + randTo) + "_") + randsCount) + "_") + remainingRands) + "_") + dataDoneTxId) + "_") + lastOffset)
47+func formatStateDataStr (drawState,organizerPubKey58,randFrom,randTo,randsCount,remainingRands,dataKeysCount,dataDoneTxId,lastOffset,slowIdx1,slowIdx2,fastIdx1,fastIdx2,randOrEmpty) = {
48+ let fullStateStr = ((((((((((((((((((((((((drawState + "_") + organizerPubKey58) + "_") + randFrom) + "_") + randTo) + "_") + randsCount) + "_") + remainingRands) + "_") + dataKeysCount) + "_") + dataDoneTxId) + "_") + lastOffset) + "_") + slowIdx1) + "_") + slowIdx2) + "_") + fastIdx1) + "_") + fastIdx2)
4749 if ((randOrEmpty == ""))
4850 then ((fullStateStr + "_") + "-")
4951 else ((fullStateStr + "_") + randOrEmpty)
6870 }
6971
7072
71-func generateRand (sessionId,from,to,rsaSign,currRandsStr,remainingRands,lastOffsetBytes) = {
72- let randHash = rsaSign
73+func generateRand (sessionId,from,to,rsaSign,currRandsStr,remainingRands,lastOffsetBytes,currSlowIdx1,currSlowIdx2,currFastIdx1,currFastIdx2) = {
74+ let newIncList = if (((lastOffsetBytes + 1) > 87))
75+ then if ((currFastIdx2 > 241))
76+ then [0, (currSlowIdx1 + 1), (currSlowIdx2 + 1), 0, 1]
77+ else [0, currSlowIdx1, currSlowIdx2, (currFastIdx1 + 1), (currFastIdx2 + 1)]
78+ else [(lastOffsetBytes + 1), currSlowIdx1, currSlowIdx2, currFastIdx1, currFastIdx2]
79+ let newOffsetBytes = newIncList[0]
80+ let newSlowIdx1 = newIncList[1]
81+ let newSlowIdx2 = newIncList[2]
82+ let newFastIdx1 = newIncList[3]
83+ let newFastIdx2 = newIncList[4]
84+ let byteVect = (((((((take(drop(rsaSign, newSlowIdx1), 1) + take(drop(rsaSign, 1), 1)) + take(drop(rsaSign, newFastIdx1), 1)) + take(drop(rsaSign, 3), 1)) + take(drop(rsaSign, newSlowIdx2), 1)) + take(drop(rsaSign, 5), 1)) + take(drop(rsaSign, 6), 1)) + take(drop(rsaSign, newFastIdx2), 1))
85+ let randHash = ((sha256(byteVect) + blake2b256(byteVect)) + keccak256(byteVect))
7386 let div = ((to - from) + 1)
74- let rand1 = nextRand(div, from, currRandsStr, remainingRands, drop(randHash, (lastOffsetBytes + 1)))
87+ let rand1 = nextRand(div, from, currRandsStr, remainingRands, drop(randHash, newOffsetBytes))
7588 let rem1 = if ((rand1[1] != ""))
7689 then (remainingRands - 1)
7790 else remainingRands
78- let rand2 = nextRand(div, from, rand1[0], rem1, drop(randHash, (lastOffsetBytes + 2)))
91+ let rand2 = nextRand(div, from, rand1[0], rem1, drop(randHash, (newOffsetBytes + 1)))
7992 let rem2 = if ((rand2[1] != ""))
8093 then (rem1 - 1)
8194 else rem1
82- let rand3 = nextRand(div, from, rand2[0], rem2, drop(randHash, (lastOffsetBytes + 3)))
95+ let rand3 = nextRand(div, from, rand2[0], rem2, drop(randHash, (newOffsetBytes + 2)))
8396 let rem3 = if ((rand3[1] != ""))
8497 then (rem2 - 1)
8598 else rem2
86- let rand4 = nextRand(div, from, rand3[0], rem3, drop(randHash, (lastOffsetBytes + 4)))
99+ let rand4 = nextRand(div, from, rand3[0], rem3, drop(randHash, (newOffsetBytes + 3)))
87100 let rem4 = if ((rand4[1] != ""))
88101 then (rem3 - 1)
89102 else rem3
90- let rand5 = nextRand(div, from, rand4[0], rem4, drop(randHash, (lastOffsetBytes + 5)))
103+ let rand5 = nextRand(div, from, rand4[0], rem4, drop(randHash, (newOffsetBytes + 4)))
91104 let rem5 = if ((rand5[1] != ""))
92105 then (rem4 - 1)
93106 else rem4
94- let rand6 = nextRand(div, from, rand5[0], rem5, drop(randHash, (lastOffsetBytes + 6)))
107+ let rand6 = nextRand(div, from, rand5[0], rem5, drop(randHash, (newOffsetBytes + 5)))
95108 let rem6 = if ((rand6[1] != ""))
96109 then (rem5 - 1)
97110 else rem5
98- let rand7 = nextRand(div, from, rand6[0], rem6, drop(randHash, (lastOffsetBytes + 7)))
111+ let rand7 = nextRand(div, from, rand6[0], rem6, drop(randHash, (newOffsetBytes + 6)))
99112 let rem7 = if ((rand7[1] != ""))
100113 then (rem6 - 1)
101114 else rem6
102- let rand8 = nextRand(div, from, rand7[0], rem7, drop(randHash, (lastOffsetBytes + 8)))
115+ let rand8 = nextRand(div, from, rand7[0], rem7, drop(randHash, (newOffsetBytes + 7)))
103116 let rem8 = if ((rand8[1] != ""))
104117 then (rem7 - 1)
105118 else rem7
106- let rand9 = nextRand(div, from, rand8[0], rem8, drop(randHash, (lastOffsetBytes + 9)))
119+ let rand9 = nextRand(div, from, rand8[0], rem8, drop(randHash, (newOffsetBytes + 8)))
107120 let rem9 = if ((rand9[1] != ""))
108121 then (rem8 - 1)
109122 else rem8
110- let rand10 = nextRand(div, from, rand9[0], rem9, drop(randHash, (lastOffsetBytes + 10)))
123+ let rand10 = nextRand(div, from, rand9[0], rem9, drop(randHash, (newOffsetBytes + 9)))
111124 let rem10 = if ((rand10[1] != ""))
112125 then (rem9 - 1)
113126 else rem9
114- let rand11 = nextRand(div, from, rand10[0], rem10, drop(randHash, (lastOffsetBytes + 11)))
127+ let rand11 = nextRand(div, from, rand10[0], rem10, drop(randHash, (newOffsetBytes + 10)))
115128 let rem11 = if ((rand11[1] != ""))
116129 then (rem10 - 1)
117130 else rem10
118- let rand12 = nextRand(div, from, rand11[0], rem11, drop(randHash, (lastOffsetBytes + 12)))
119- let rem12 = if ((rand12[1] != ""))
120- then (rem11 - 1)
121- else rem11
122- let rand13 = nextRand(div, from, rand12[0], rem12, drop(randHash, (lastOffsetBytes + 13)))
123- let rem13 = if ((rand13[1] != ""))
124- then (rem12 - 1)
125- else rem12
126- let rand14 = nextRand(div, from, rand13[0], rem13, drop(randHash, (lastOffsetBytes + 14)))
127- let rem14 = if ((rand14[1] != ""))
128- then (rem13 - 1)
129- else rem13
130-[rand14[0], if ((rem14 == 0))
131+[rand11[0], if ((rem11 == 0))
131132 then "0"
132- else toString(rem14), toString((lastOffsetBytes + 14))]
133+ else toString(rem11), toString((newOffsetBytes + 10)), toString(newSlowIdx1), toString(newSlowIdx2), toString(newFastIdx1), toString(newFastIdx2)]
133134 }
134135
135136
136-func validateDtxKey (sessionId,data) = if (if (if ((sessionId == take(data.key, SESSIONIDFIXSIZE)))
137- then (size(data.key) > SESSIONIDFIXSIZE)
138- else false)
139- then !(isDefined(getString(this, data.key)))
140- else false)
141- then match data.value {
142- case str: String =>
143- true
144- case _ =>
145- throw((sessionId + " draw: only String type is accepted for data transactions"))
137+func validateDtxKey (sessionId,dataKeysCount,data) = {
138+ let dataKeyInfo = split(data.key, "_")
139+ if ((size(dataKeyInfo) != 2))
140+ then throw("Invalid data key format. It must follow to ${sessionId}_${num}")
141+ else {
142+ let keySessionId = dataKeyInfo[0]
143+ let keyPostfix = dataKeyInfo[1]
144+ if ((sessionId != keySessionId))
145+ then throw(((("Several data keys have different sessionId: " + sessionId) + " and ") + keySessionId))
146+ else if (isDefined(getString(this, data.key)))
147+ then throw(("One of the data keys has already presented in account state: key=" + data.key))
148+ else if ((size(keyPostfix) > 4))
149+ then throw("Invalid data key format. It must follow to ${sessionId}_${num} where ${num} length couldn't be greater than 4")
150+ else if ((take(keyPostfix, 1) == "0"))
151+ then throw("Invalid data key format. It must follow to ${sessionId}_${num} where ${num} couldn't start from 0")
152+ else {
153+ let keyPostfixIntOpt = parseInt(keyPostfix)
154+ if (isDefined(keyPostfixIntOpt))
155+ then {
156+ let keyPostfixInt = extract(keyPostfixIntOpt)
157+ if (if ((1 > keyPostfixInt))
158+ then true
159+ else (keyPostfixInt > dataKeysCount))
160+ then throw((((("Invalid data key format. It must follow to ${sessionId}_${num}" + " where ${num} must be a valid int value from 1 to ") + toString(dataKeysCount)) + " but actualNum=") + toString(keyPostfixInt)))
161+ else match data.value {
162+ case str: String =>
163+ true
164+ case _ =>
165+ throw((sessionId + " draw: only String type is accepted for data transactions"))
166+ }
167+ }
168+ else throw((("Invalid data key format. It must follow to ${sessionId}_${num}" + " where ${num} must be a valid int value from 1 to 7145 but actualNum=") + keyPostfix))
169+ }
170+ }
146171 }
147- else false
172+
173+
174+func validateAndGetRandsPmt (randsCount,pmt,minDataPmt) = {
175+ let bound1 = 1000
176+ let basePrice1 = ((13 * WAVELET) / 100)
177+ let div1 = 50
178+ let diff1 = ((8 * WAVELET) / 100)
179+ let bound2 = 5000
180+ let basePrice2 = ((297 * WAVELET) / 100)
181+ let div2 = 1000
182+ let diff2 = ((143 * WAVELET) / 100)
183+ let bound3 = 50000
184+ let basePrice3 = ((1427 * WAVELET) / 100)
185+ let div3 = 5000
186+ let diff3 = ((705 * WAVELET) / 100)
187+ let minRandsPmt = if ((bound1 > randsCount))
188+ then (basePrice1 + ((randsCount / div1) * diff1))
189+ else if ((bound2 > randsCount))
190+ then (basePrice2 + (((randsCount / div2) - 1) * diff2))
191+ else if ((bound3 > randsCount))
192+ then (basePrice3 + (((randsCount / div3) - 1) * diff3))
193+ else throw("Please contact our sales team to generate more than 50k rands")
194+ let minPmt = (minRandsPmt + minDataPmt)
195+ if (isDefined(pmt.assetId))
196+ then throw("Only WAVES can be used as a payment for rands generation")
197+ else if ((minPmt > pmt.amount))
198+ then throw(((((("Attached payment is to small to generate " + toString(randsCount)) + " unique randoms numbers and upload at least 1 data tx: actualPmt=") + toString(pmt.amount)) + " but minPmt is ") + toString(minPmt)))
199+ else minRandsPmt
200+ }
148201
149202
150203 @Callable(i)
151204 func initDraw (randFrom,randTo,randsCount) = {
152205 let sessionId = toBase58String(i.transactionId)
206+ let rangeLength = ((randTo - randFrom) + 1)
207+ let maxRangeLength = (rangeLength / 2)
208+ let randToLen = size(toString((randTo - 1)))
209+ let randsCountLen = size(toString(randsCount))
210+ let dynamicStatusLen = (((2 * randToLen) + (2 * randsCountLen)) + 4)
211+ let maxRandsCount = (((5120 - 175) - dynamicStatusLen) / (randToLen + 1))
153212 if (if ((0 >= randFrom))
154213 then true
155214 else (0 >= randTo))
156215 then throw("randFrom and randTo must be greater than 0")
157216 else if ((randFrom >= randTo))
158217 then throw("randFrom must be strict less then randTo")
159- else if ((randsCount > ((randTo - randFrom) + 1)))
160- then throw(((((("Impossible to generate " + toString(randsCount)) + " for provided random range - from ") + toString(randFrom)) + " to ") + toString(randTo)))
161- else {
162- let organizerPubKey58 = toBase58String(i.callerPublicKey)
163- let randsCountStr = toString(randsCount)
164- let initState = formatStateDataStr(STATEINIT, organizerPubKey58, toString(randFrom), toString(randTo), randsCountStr, randsCountStr, "null", "0", "")
165- ScriptResult(WriteSet([DataEntry(sessionId, initState)]), TransferSet([ScriptTransfer(SERVER, 1000, unit)]))
166- }
218+ else if ((randsCount > rangeLength))
219+ then throw(((((((("Impossible to generate " + toString(randsCount)) + " unique numbers for provided random range [") + toString(randFrom)) + ", ") + toString(randTo)) + "] with actual size ") + toString(rangeLength)))
220+ else if ((randsCount > maxRangeLength))
221+ then throw(((((((((("randsCount must be less then 50% of passed range length: range=[" + toString(randFrom)) + ", ") + toString(randTo)) + "], rangeLength=") + toString(rangeLength)) + " randsCount=") + toString(randsCount)) + " allowedRandsCount=") + toString(maxRangeLength)))
222+ else if ((randsCount > maxRandsCount))
223+ then throw(((((("randsCount couldn't be kept in 1 data entry: 1_randNumSpace=" + toString((randToLen + 1))) + " maxAllowedRandsCount=") + toString(maxRandsCount)) + " actualRandsCount=") + toString(randsCount)))
224+ else if (!(isDefined(i.payment)))
225+ then throw("Please provide payment to generate unique random numbers")
226+ else {
227+ let pmt = extract(i.payment)
228+ let minDataPmt = ((5 * WAVELET) / 1000)
229+ let randsPmt = validateAndGetRandsPmt(randsCount, pmt, minDataPmt)
230+ let dataPmt = (pmt.amount - randsPmt)
231+ let dataTxCount = (dataPmt / minDataPmt)
232+ let dataKeysCount = if ((7145 >= (dataTxCount * 5)))
233+ then (dataTxCount * 5)
234+ else 7145
235+ let organizerPubKey58 = toBase58String(i.callerPublicKey)
236+ let randsCountStr = toString(randsCount)
237+ let initState = formatStateDataStr(STATEINIT, organizerPubKey58, toString(randFrom), toString(randTo), randsCountStr, randsCountStr, toString(dataKeysCount), "null", "0", "0", "1", "0", "1", "")
238+ ScriptResult(WriteSet([DataEntry(sessionId, initState)]), TransferSet([ScriptTransfer(SERVER, randsPmt, unit)]))
239+ }
167240 }
168241
169242
177250 let remainRandsCountStr = drawParamsList[IdxRemainRandsCount]
178251 let fromStr = drawParamsList[IdxRandFrom]
179252 let toStr = drawParamsList[IdxRandTo]
253+ let dataKeysCount = drawParamsList[IdxDataKeysCount]
180254 let organizerPubKey = fromBase58String(organizerPubKey58)
181255 if ((drawState != STATEINIT))
182256 then throw((sessionId + " draw: moving into READY state is allowed only from INIT state"))
183257 else if ((organizerPubKey != i.callerPublicKey))
184258 then throw((sessionId + "draw: moving into READY state is allowed for organizer only"))
185259 else {
186- let readyState = formatStateDataStr(DATADONE, organizerPubKey58, fromStr, toStr, randsCountStr, remainRandsCountStr, toBase58String(i.transactionId), "0", "")
260+ let readyState = formatStateDataStr(DATADONE, organizerPubKey58, fromStr, toStr, randsCountStr, remainRandsCountStr, dataKeysCount, toBase58String(i.transactionId), "0", "0", "1", "0", "1", "")
187261 WriteSet([DataEntry(sessionId, readyState)])
188262 }
189263 }
202276 let fromStr = drawParamsList[IdxRandFrom]
203277 let toStr = drawParamsList[IdxRandTo]
204278 let dataDoneTxId = drawParamsList[IdxDataDoneTxId]
279+ let slowIdx1 = parseIntValue(drawParamsList[9])
280+ let slowIdx2 = parseIntValue(drawParamsList[10])
281+ let fastIdx1 = parseIntValue(drawParamsList[11])
282+ let fastIdx2 = parseIntValue(drawParamsList[12])
205283 let from = parseIntValue(fromStr)
206284 let to = parseIntValue(toStr)
207285 let organizerPubKey = fromBase58String(organizerPubKey58)
210288 else if (!(rsaVerify(SHA256, (toBytes(sessionId) + toBytes(dataDoneTxId)), rsaSign, RSAPUBLIC)))
211289 then throw("Invalid RSA signature")
212290 else {
213- let randGenInfo = generateRand(sessionId, from, to, rsaSign, currRandsStr, remainRandsCount, lastOffsetBytes)
214- let newRandsStr = randGenInfo[0]
291+ let randGenInfo = generateRand(sessionId, from, to, rsaSign, currRandsStr, remainRandsCount, lastOffsetBytes, slowIdx1, slowIdx2, fastIdx1, fastIdx2)
215292 let newRemainRandsCountStr = randGenInfo[1]
216- let newOffsetBytes = randGenInfo[2]
217293 let newState = if ((newRemainRandsCountStr == "0"))
218294 then STATEFINISHED
219295 else DATADONE
220- WriteSet([DataEntry(sessionId, formatStateDataStr(newState, organizerPubKey58, fromStr, toStr, randsCountStr, newRemainRandsCountStr, dataDoneTxId, newOffsetBytes, newRandsStr))])
296+ WriteSet([DataEntry(sessionId, formatStateDataStr(newState, organizerPubKey58, fromStr, toStr, randsCountStr, newRemainRandsCountStr, drawParamsList[IdxDataKeysCount], dataDoneTxId, randGenInfo[2], randGenInfo[3], randGenInfo[4], randGenInfo[5], randGenInfo[6], randGenInfo[0]))])
221297 }
222298 }
223299
228304 let data0 = dtx.data[0]
229305 let sessionId = take(data0.key, SESSIONIDFIXSIZE)
230306 let drawParamsList = extractGameDataList(sessionId)
231- let drawState = drawParamsList[0]
232- let organizerPubKey58 = drawParamsList[1]
307+ let drawState = drawParamsList[IdxState]
308+ let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
309+ let dataKeysCount = parseIntValue(drawParamsList[IdxDataKeysCount])
233310 let organizerPubKey = fromBase58String(organizerPubKey58)
234311 let dataEntriesCount = size(dtx.data)
235312 let sigValid = sigVerify(tx.bodyBytes, tx.proofs[0], organizerPubKey)
236- let dataSizeValid = if ((dataEntriesCount > 0))
237- then (5 >= dataEntriesCount)
313+ let dataSizeValid = (dataEntriesCount == 5)
314+ let feeValid = (dtx.fee == ((WAVELET * 5) / 1000))
315+ let keysValid = if (if (if (if (validateDtxKey(sessionId, dataKeysCount, data0))
316+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[1])
317+ else false)
318+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[2])
319+ else false)
320+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[3])
321+ else false)
322+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[4])
238323 else false
239- let keysValid = if (if (if (if (if (validateDtxKey(sessionId, data0))
240- then if ((1 >= dataEntriesCount))
241- then true
242- else validateDtxKey(sessionId, dtx.data[1])
324+ if (if (if (if ((drawState == STATEINIT))
325+ then sigValid
243326 else false)
244- then if ((2 >= dataEntriesCount))
245- then true
246- else validateDtxKey(sessionId, dtx.data[2])
247- else false)
248- then if ((3 >= dataEntriesCount))
249- then true
250- else validateDtxKey(sessionId, dtx.data[3])
251- else false)
252- then if ((4 >= dataEntriesCount))
253- then true
254- else validateDtxKey(sessionId, dtx.data[4])
255- else false)
256- then if ((5 >= dataEntriesCount))
257- then true
258- else validateDtxKey(sessionId, dtx.data[5])
259- else false
260- if (if (if ((drawState == STATEINIT))
261- then sigValid
327+ then feeValid
262328 else false)
263329 then dataSizeValid
264330 else false)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 3 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let RSAPUBLIC = fromBase64String("base64:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqlAiANSmBpDHYKP9sKgeN/l1bAb28g/tGlgDkwT5FiMN4X3pwdvdxE7mvSR8/41dU9rx4jG+6tZpb1ULVDPs431tR2IRaTXw5Cj+Ac2vhL+5JamCerGD1UW+bh/EGQtxo8W3YLDrofXB5QHJx4Pkz2Kgf+oS/C8hHuB/U4krO76U0507GTjZPP9kRQ0uLSMeqQXt8wXS+nMp5wajqxPpDLMaSREgsKwv/AEkP4dzpTYbikLBYl4qtdJsD84HLFSkiwd3BhcOrPjoIYmLxQuBD5TIMKTKD3sdZgaY9rsyqx3A00innyxD6zp3b4gFpUOX8JxKZdEC2myEqleNgg7GzwIDAQAB")
55
66 let SERVER = addressFromStringValue("3NCiG28LmWyTigWG13E5QnvdHBsZFYXSS2j")
77
88 let WAVELET = ((100 * 1000) * 1000)
99
1010 let SESSIONIDFIXSIZE = 44
1111
1212 let RANDCYCLEPRICE = ((5 * WAVELET) / 1000)
1313
1414 let MAXRANDSPERCYCLE = 14
1515
1616 let STATEINIT = "INIT"
1717
1818 let DATADONE = "READY"
1919
2020 let STATEFINISHED = "FINISHED"
2121
2222 let IdxState = 0
2323
2424 let IdxOrganizerPub = 1
2525
2626 let IdxRandFrom = 2
2727
2828 let IdxRandTo = 3
2929
3030 let IdxRandsCount = 4
3131
3232 let IdxRemainRandsCount = 5
3333
34-let IdxDataDoneTxId = 6
34+let IdxDataKeysCount = 6
3535
36-let IdxLastOffset = 7
36+let IdxDataDoneTxId = 7
3737
38-let IdxCurrRands = 8
38+let IdxLastOffset = 8
39+
40+let IdxCurrRands = 13
3941
4042 func abs (val) = if ((0 > val))
4143 then -(val)
4244 else val
4345
4446
45-func formatStateDataStr (drawState,organizerPubKey58,randFrom,randTo,randsCount,remainingRands,dataDoneTxId,lastOffset,randOrEmpty) = {
46- let fullStateStr = ((((((((((((((drawState + "_") + organizerPubKey58) + "_") + randFrom) + "_") + randTo) + "_") + randsCount) + "_") + remainingRands) + "_") + dataDoneTxId) + "_") + lastOffset)
47+func formatStateDataStr (drawState,organizerPubKey58,randFrom,randTo,randsCount,remainingRands,dataKeysCount,dataDoneTxId,lastOffset,slowIdx1,slowIdx2,fastIdx1,fastIdx2,randOrEmpty) = {
48+ let fullStateStr = ((((((((((((((((((((((((drawState + "_") + organizerPubKey58) + "_") + randFrom) + "_") + randTo) + "_") + randsCount) + "_") + remainingRands) + "_") + dataKeysCount) + "_") + dataDoneTxId) + "_") + lastOffset) + "_") + slowIdx1) + "_") + slowIdx2) + "_") + fastIdx1) + "_") + fastIdx2)
4749 if ((randOrEmpty == ""))
4850 then ((fullStateStr + "_") + "-")
4951 else ((fullStateStr + "_") + randOrEmpty)
5052 }
5153
5254
5355 func extractGameDataList (sessionId) = {
5456 let rawDataStr = getStringValue(this, sessionId)
5557 split(rawDataStr, "_")
5658 }
5759
5860
5961 func nextRand (div,min,currRandsStr,remainingRands,remainingHash) = {
6062 let nextRandInt = ((abs(toInt(remainingHash)) % div) + min)
6163 let nextRandStr = toString(nextRandInt)
6264 let duplicate = isDefined(indexOf(currRandsStr, nextRandStr))
6365 if (if (!(duplicate))
6466 then (remainingRands > 0)
6567 else false)
6668 then [((currRandsStr + "-") + nextRandStr), "yes"]
6769 else [currRandsStr, ""]
6870 }
6971
7072
71-func generateRand (sessionId,from,to,rsaSign,currRandsStr,remainingRands,lastOffsetBytes) = {
72- let randHash = rsaSign
73+func generateRand (sessionId,from,to,rsaSign,currRandsStr,remainingRands,lastOffsetBytes,currSlowIdx1,currSlowIdx2,currFastIdx1,currFastIdx2) = {
74+ let newIncList = if (((lastOffsetBytes + 1) > 87))
75+ then if ((currFastIdx2 > 241))
76+ then [0, (currSlowIdx1 + 1), (currSlowIdx2 + 1), 0, 1]
77+ else [0, currSlowIdx1, currSlowIdx2, (currFastIdx1 + 1), (currFastIdx2 + 1)]
78+ else [(lastOffsetBytes + 1), currSlowIdx1, currSlowIdx2, currFastIdx1, currFastIdx2]
79+ let newOffsetBytes = newIncList[0]
80+ let newSlowIdx1 = newIncList[1]
81+ let newSlowIdx2 = newIncList[2]
82+ let newFastIdx1 = newIncList[3]
83+ let newFastIdx2 = newIncList[4]
84+ let byteVect = (((((((take(drop(rsaSign, newSlowIdx1), 1) + take(drop(rsaSign, 1), 1)) + take(drop(rsaSign, newFastIdx1), 1)) + take(drop(rsaSign, 3), 1)) + take(drop(rsaSign, newSlowIdx2), 1)) + take(drop(rsaSign, 5), 1)) + take(drop(rsaSign, 6), 1)) + take(drop(rsaSign, newFastIdx2), 1))
85+ let randHash = ((sha256(byteVect) + blake2b256(byteVect)) + keccak256(byteVect))
7386 let div = ((to - from) + 1)
74- let rand1 = nextRand(div, from, currRandsStr, remainingRands, drop(randHash, (lastOffsetBytes + 1)))
87+ let rand1 = nextRand(div, from, currRandsStr, remainingRands, drop(randHash, newOffsetBytes))
7588 let rem1 = if ((rand1[1] != ""))
7689 then (remainingRands - 1)
7790 else remainingRands
78- let rand2 = nextRand(div, from, rand1[0], rem1, drop(randHash, (lastOffsetBytes + 2)))
91+ let rand2 = nextRand(div, from, rand1[0], rem1, drop(randHash, (newOffsetBytes + 1)))
7992 let rem2 = if ((rand2[1] != ""))
8093 then (rem1 - 1)
8194 else rem1
82- let rand3 = nextRand(div, from, rand2[0], rem2, drop(randHash, (lastOffsetBytes + 3)))
95+ let rand3 = nextRand(div, from, rand2[0], rem2, drop(randHash, (newOffsetBytes + 2)))
8396 let rem3 = if ((rand3[1] != ""))
8497 then (rem2 - 1)
8598 else rem2
86- let rand4 = nextRand(div, from, rand3[0], rem3, drop(randHash, (lastOffsetBytes + 4)))
99+ let rand4 = nextRand(div, from, rand3[0], rem3, drop(randHash, (newOffsetBytes + 3)))
87100 let rem4 = if ((rand4[1] != ""))
88101 then (rem3 - 1)
89102 else rem3
90- let rand5 = nextRand(div, from, rand4[0], rem4, drop(randHash, (lastOffsetBytes + 5)))
103+ let rand5 = nextRand(div, from, rand4[0], rem4, drop(randHash, (newOffsetBytes + 4)))
91104 let rem5 = if ((rand5[1] != ""))
92105 then (rem4 - 1)
93106 else rem4
94- let rand6 = nextRand(div, from, rand5[0], rem5, drop(randHash, (lastOffsetBytes + 6)))
107+ let rand6 = nextRand(div, from, rand5[0], rem5, drop(randHash, (newOffsetBytes + 5)))
95108 let rem6 = if ((rand6[1] != ""))
96109 then (rem5 - 1)
97110 else rem5
98- let rand7 = nextRand(div, from, rand6[0], rem6, drop(randHash, (lastOffsetBytes + 7)))
111+ let rand7 = nextRand(div, from, rand6[0], rem6, drop(randHash, (newOffsetBytes + 6)))
99112 let rem7 = if ((rand7[1] != ""))
100113 then (rem6 - 1)
101114 else rem6
102- let rand8 = nextRand(div, from, rand7[0], rem7, drop(randHash, (lastOffsetBytes + 8)))
115+ let rand8 = nextRand(div, from, rand7[0], rem7, drop(randHash, (newOffsetBytes + 7)))
103116 let rem8 = if ((rand8[1] != ""))
104117 then (rem7 - 1)
105118 else rem7
106- let rand9 = nextRand(div, from, rand8[0], rem8, drop(randHash, (lastOffsetBytes + 9)))
119+ let rand9 = nextRand(div, from, rand8[0], rem8, drop(randHash, (newOffsetBytes + 8)))
107120 let rem9 = if ((rand9[1] != ""))
108121 then (rem8 - 1)
109122 else rem8
110- let rand10 = nextRand(div, from, rand9[0], rem9, drop(randHash, (lastOffsetBytes + 10)))
123+ let rand10 = nextRand(div, from, rand9[0], rem9, drop(randHash, (newOffsetBytes + 9)))
111124 let rem10 = if ((rand10[1] != ""))
112125 then (rem9 - 1)
113126 else rem9
114- let rand11 = nextRand(div, from, rand10[0], rem10, drop(randHash, (lastOffsetBytes + 11)))
127+ let rand11 = nextRand(div, from, rand10[0], rem10, drop(randHash, (newOffsetBytes + 10)))
115128 let rem11 = if ((rand11[1] != ""))
116129 then (rem10 - 1)
117130 else rem10
118- let rand12 = nextRand(div, from, rand11[0], rem11, drop(randHash, (lastOffsetBytes + 12)))
119- let rem12 = if ((rand12[1] != ""))
120- then (rem11 - 1)
121- else rem11
122- let rand13 = nextRand(div, from, rand12[0], rem12, drop(randHash, (lastOffsetBytes + 13)))
123- let rem13 = if ((rand13[1] != ""))
124- then (rem12 - 1)
125- else rem12
126- let rand14 = nextRand(div, from, rand13[0], rem13, drop(randHash, (lastOffsetBytes + 14)))
127- let rem14 = if ((rand14[1] != ""))
128- then (rem13 - 1)
129- else rem13
130-[rand14[0], if ((rem14 == 0))
131+[rand11[0], if ((rem11 == 0))
131132 then "0"
132- else toString(rem14), toString((lastOffsetBytes + 14))]
133+ else toString(rem11), toString((newOffsetBytes + 10)), toString(newSlowIdx1), toString(newSlowIdx2), toString(newFastIdx1), toString(newFastIdx2)]
133134 }
134135
135136
136-func validateDtxKey (sessionId,data) = if (if (if ((sessionId == take(data.key, SESSIONIDFIXSIZE)))
137- then (size(data.key) > SESSIONIDFIXSIZE)
138- else false)
139- then !(isDefined(getString(this, data.key)))
140- else false)
141- then match data.value {
142- case str: String =>
143- true
144- case _ =>
145- throw((sessionId + " draw: only String type is accepted for data transactions"))
137+func validateDtxKey (sessionId,dataKeysCount,data) = {
138+ let dataKeyInfo = split(data.key, "_")
139+ if ((size(dataKeyInfo) != 2))
140+ then throw("Invalid data key format. It must follow to ${sessionId}_${num}")
141+ else {
142+ let keySessionId = dataKeyInfo[0]
143+ let keyPostfix = dataKeyInfo[1]
144+ if ((sessionId != keySessionId))
145+ then throw(((("Several data keys have different sessionId: " + sessionId) + " and ") + keySessionId))
146+ else if (isDefined(getString(this, data.key)))
147+ then throw(("One of the data keys has already presented in account state: key=" + data.key))
148+ else if ((size(keyPostfix) > 4))
149+ then throw("Invalid data key format. It must follow to ${sessionId}_${num} where ${num} length couldn't be greater than 4")
150+ else if ((take(keyPostfix, 1) == "0"))
151+ then throw("Invalid data key format. It must follow to ${sessionId}_${num} where ${num} couldn't start from 0")
152+ else {
153+ let keyPostfixIntOpt = parseInt(keyPostfix)
154+ if (isDefined(keyPostfixIntOpt))
155+ then {
156+ let keyPostfixInt = extract(keyPostfixIntOpt)
157+ if (if ((1 > keyPostfixInt))
158+ then true
159+ else (keyPostfixInt > dataKeysCount))
160+ then throw((((("Invalid data key format. It must follow to ${sessionId}_${num}" + " where ${num} must be a valid int value from 1 to ") + toString(dataKeysCount)) + " but actualNum=") + toString(keyPostfixInt)))
161+ else match data.value {
162+ case str: String =>
163+ true
164+ case _ =>
165+ throw((sessionId + " draw: only String type is accepted for data transactions"))
166+ }
167+ }
168+ else throw((("Invalid data key format. It must follow to ${sessionId}_${num}" + " where ${num} must be a valid int value from 1 to 7145 but actualNum=") + keyPostfix))
169+ }
170+ }
146171 }
147- else false
172+
173+
174+func validateAndGetRandsPmt (randsCount,pmt,minDataPmt) = {
175+ let bound1 = 1000
176+ let basePrice1 = ((13 * WAVELET) / 100)
177+ let div1 = 50
178+ let diff1 = ((8 * WAVELET) / 100)
179+ let bound2 = 5000
180+ let basePrice2 = ((297 * WAVELET) / 100)
181+ let div2 = 1000
182+ let diff2 = ((143 * WAVELET) / 100)
183+ let bound3 = 50000
184+ let basePrice3 = ((1427 * WAVELET) / 100)
185+ let div3 = 5000
186+ let diff3 = ((705 * WAVELET) / 100)
187+ let minRandsPmt = if ((bound1 > randsCount))
188+ then (basePrice1 + ((randsCount / div1) * diff1))
189+ else if ((bound2 > randsCount))
190+ then (basePrice2 + (((randsCount / div2) - 1) * diff2))
191+ else if ((bound3 > randsCount))
192+ then (basePrice3 + (((randsCount / div3) - 1) * diff3))
193+ else throw("Please contact our sales team to generate more than 50k rands")
194+ let minPmt = (minRandsPmt + minDataPmt)
195+ if (isDefined(pmt.assetId))
196+ then throw("Only WAVES can be used as a payment for rands generation")
197+ else if ((minPmt > pmt.amount))
198+ then throw(((((("Attached payment is to small to generate " + toString(randsCount)) + " unique randoms numbers and upload at least 1 data tx: actualPmt=") + toString(pmt.amount)) + " but minPmt is ") + toString(minPmt)))
199+ else minRandsPmt
200+ }
148201
149202
150203 @Callable(i)
151204 func initDraw (randFrom,randTo,randsCount) = {
152205 let sessionId = toBase58String(i.transactionId)
206+ let rangeLength = ((randTo - randFrom) + 1)
207+ let maxRangeLength = (rangeLength / 2)
208+ let randToLen = size(toString((randTo - 1)))
209+ let randsCountLen = size(toString(randsCount))
210+ let dynamicStatusLen = (((2 * randToLen) + (2 * randsCountLen)) + 4)
211+ let maxRandsCount = (((5120 - 175) - dynamicStatusLen) / (randToLen + 1))
153212 if (if ((0 >= randFrom))
154213 then true
155214 else (0 >= randTo))
156215 then throw("randFrom and randTo must be greater than 0")
157216 else if ((randFrom >= randTo))
158217 then throw("randFrom must be strict less then randTo")
159- else if ((randsCount > ((randTo - randFrom) + 1)))
160- then throw(((((("Impossible to generate " + toString(randsCount)) + " for provided random range - from ") + toString(randFrom)) + " to ") + toString(randTo)))
161- else {
162- let organizerPubKey58 = toBase58String(i.callerPublicKey)
163- let randsCountStr = toString(randsCount)
164- let initState = formatStateDataStr(STATEINIT, organizerPubKey58, toString(randFrom), toString(randTo), randsCountStr, randsCountStr, "null", "0", "")
165- ScriptResult(WriteSet([DataEntry(sessionId, initState)]), TransferSet([ScriptTransfer(SERVER, 1000, unit)]))
166- }
218+ else if ((randsCount > rangeLength))
219+ then throw(((((((("Impossible to generate " + toString(randsCount)) + " unique numbers for provided random range [") + toString(randFrom)) + ", ") + toString(randTo)) + "] with actual size ") + toString(rangeLength)))
220+ else if ((randsCount > maxRangeLength))
221+ then throw(((((((((("randsCount must be less then 50% of passed range length: range=[" + toString(randFrom)) + ", ") + toString(randTo)) + "], rangeLength=") + toString(rangeLength)) + " randsCount=") + toString(randsCount)) + " allowedRandsCount=") + toString(maxRangeLength)))
222+ else if ((randsCount > maxRandsCount))
223+ then throw(((((("randsCount couldn't be kept in 1 data entry: 1_randNumSpace=" + toString((randToLen + 1))) + " maxAllowedRandsCount=") + toString(maxRandsCount)) + " actualRandsCount=") + toString(randsCount)))
224+ else if (!(isDefined(i.payment)))
225+ then throw("Please provide payment to generate unique random numbers")
226+ else {
227+ let pmt = extract(i.payment)
228+ let minDataPmt = ((5 * WAVELET) / 1000)
229+ let randsPmt = validateAndGetRandsPmt(randsCount, pmt, minDataPmt)
230+ let dataPmt = (pmt.amount - randsPmt)
231+ let dataTxCount = (dataPmt / minDataPmt)
232+ let dataKeysCount = if ((7145 >= (dataTxCount * 5)))
233+ then (dataTxCount * 5)
234+ else 7145
235+ let organizerPubKey58 = toBase58String(i.callerPublicKey)
236+ let randsCountStr = toString(randsCount)
237+ let initState = formatStateDataStr(STATEINIT, organizerPubKey58, toString(randFrom), toString(randTo), randsCountStr, randsCountStr, toString(dataKeysCount), "null", "0", "0", "1", "0", "1", "")
238+ ScriptResult(WriteSet([DataEntry(sessionId, initState)]), TransferSet([ScriptTransfer(SERVER, randsPmt, unit)]))
239+ }
167240 }
168241
169242
170243
171244 @Callable(i)
172245 func ready (sessionId) = {
173246 let drawParamsList = extractGameDataList(sessionId)
174247 let drawState = drawParamsList[IdxState]
175248 let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
176249 let randsCountStr = drawParamsList[IdxRandsCount]
177250 let remainRandsCountStr = drawParamsList[IdxRemainRandsCount]
178251 let fromStr = drawParamsList[IdxRandFrom]
179252 let toStr = drawParamsList[IdxRandTo]
253+ let dataKeysCount = drawParamsList[IdxDataKeysCount]
180254 let organizerPubKey = fromBase58String(organizerPubKey58)
181255 if ((drawState != STATEINIT))
182256 then throw((sessionId + " draw: moving into READY state is allowed only from INIT state"))
183257 else if ((organizerPubKey != i.callerPublicKey))
184258 then throw((sessionId + "draw: moving into READY state is allowed for organizer only"))
185259 else {
186- let readyState = formatStateDataStr(DATADONE, organizerPubKey58, fromStr, toStr, randsCountStr, remainRandsCountStr, toBase58String(i.transactionId), "0", "")
260+ let readyState = formatStateDataStr(DATADONE, organizerPubKey58, fromStr, toStr, randsCountStr, remainRandsCountStr, dataKeysCount, toBase58String(i.transactionId), "0", "0", "1", "0", "1", "")
187261 WriteSet([DataEntry(sessionId, readyState)])
188262 }
189263 }
190264
191265
192266
193267 @Callable(i)
194268 func random (sessionId,rsaSign) = {
195269 let drawParamsList = extractGameDataList(sessionId)
196270 let drawState = drawParamsList[IdxState]
197271 let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
198272 let randsCountStr = drawParamsList[IdxRandsCount]
199273 let remainRandsCount = parseIntValue(drawParamsList[IdxRemainRandsCount])
200274 let lastOffsetBytes = parseIntValue(drawParamsList[IdxLastOffset])
201275 let currRandsStr = drawParamsList[IdxCurrRands]
202276 let fromStr = drawParamsList[IdxRandFrom]
203277 let toStr = drawParamsList[IdxRandTo]
204278 let dataDoneTxId = drawParamsList[IdxDataDoneTxId]
279+ let slowIdx1 = parseIntValue(drawParamsList[9])
280+ let slowIdx2 = parseIntValue(drawParamsList[10])
281+ let fastIdx1 = parseIntValue(drawParamsList[11])
282+ let fastIdx2 = parseIntValue(drawParamsList[12])
205283 let from = parseIntValue(fromStr)
206284 let to = parseIntValue(toStr)
207285 let organizerPubKey = fromBase58String(organizerPubKey58)
208286 if ((drawState != DATADONE))
209287 then throw((sessionId + " draw: it must be in READY state to generate random numbers"))
210288 else if (!(rsaVerify(SHA256, (toBytes(sessionId) + toBytes(dataDoneTxId)), rsaSign, RSAPUBLIC)))
211289 then throw("Invalid RSA signature")
212290 else {
213- let randGenInfo = generateRand(sessionId, from, to, rsaSign, currRandsStr, remainRandsCount, lastOffsetBytes)
214- let newRandsStr = randGenInfo[0]
291+ let randGenInfo = generateRand(sessionId, from, to, rsaSign, currRandsStr, remainRandsCount, lastOffsetBytes, slowIdx1, slowIdx2, fastIdx1, fastIdx2)
215292 let newRemainRandsCountStr = randGenInfo[1]
216- let newOffsetBytes = randGenInfo[2]
217293 let newState = if ((newRemainRandsCountStr == "0"))
218294 then STATEFINISHED
219295 else DATADONE
220- WriteSet([DataEntry(sessionId, formatStateDataStr(newState, organizerPubKey58, fromStr, toStr, randsCountStr, newRemainRandsCountStr, dataDoneTxId, newOffsetBytes, newRandsStr))])
296+ WriteSet([DataEntry(sessionId, formatStateDataStr(newState, organizerPubKey58, fromStr, toStr, randsCountStr, newRemainRandsCountStr, drawParamsList[IdxDataKeysCount], dataDoneTxId, randGenInfo[2], randGenInfo[3], randGenInfo[4], randGenInfo[5], randGenInfo[6], randGenInfo[0]))])
221297 }
222298 }
223299
224300
225301 @Verifier(tx)
226302 func verify () = match tx {
227303 case dtx: DataTransaction =>
228304 let data0 = dtx.data[0]
229305 let sessionId = take(data0.key, SESSIONIDFIXSIZE)
230306 let drawParamsList = extractGameDataList(sessionId)
231- let drawState = drawParamsList[0]
232- let organizerPubKey58 = drawParamsList[1]
307+ let drawState = drawParamsList[IdxState]
308+ let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
309+ let dataKeysCount = parseIntValue(drawParamsList[IdxDataKeysCount])
233310 let organizerPubKey = fromBase58String(organizerPubKey58)
234311 let dataEntriesCount = size(dtx.data)
235312 let sigValid = sigVerify(tx.bodyBytes, tx.proofs[0], organizerPubKey)
236- let dataSizeValid = if ((dataEntriesCount > 0))
237- then (5 >= dataEntriesCount)
313+ let dataSizeValid = (dataEntriesCount == 5)
314+ let feeValid = (dtx.fee == ((WAVELET * 5) / 1000))
315+ let keysValid = if (if (if (if (validateDtxKey(sessionId, dataKeysCount, data0))
316+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[1])
317+ else false)
318+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[2])
319+ else false)
320+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[3])
321+ else false)
322+ then validateDtxKey(sessionId, dataKeysCount, dtx.data[4])
238323 else false
239- let keysValid = if (if (if (if (if (validateDtxKey(sessionId, data0))
240- then if ((1 >= dataEntriesCount))
241- then true
242- else validateDtxKey(sessionId, dtx.data[1])
324+ if (if (if (if ((drawState == STATEINIT))
325+ then sigValid
243326 else false)
244- then if ((2 >= dataEntriesCount))
245- then true
246- else validateDtxKey(sessionId, dtx.data[2])
247- else false)
248- then if ((3 >= dataEntriesCount))
249- then true
250- else validateDtxKey(sessionId, dtx.data[3])
251- else false)
252- then if ((4 >= dataEntriesCount))
253- then true
254- else validateDtxKey(sessionId, dtx.data[4])
255- else false)
256- then if ((5 >= dataEntriesCount))
257- then true
258- else validateDtxKey(sessionId, dtx.data[5])
259- else false
260- if (if (if ((drawState == STATEINIT))
261- then sigValid
327+ then feeValid
262328 else false)
263329 then dataSizeValid
264330 else false)
265331 then keysValid
266332 else false
267333 case sstx: SetScriptTransaction =>
268334 true
269335 case ttx: TransferTransaction =>
270336 true
271337 case _ =>
272338 false
273339 }
274340

github/deemru/w8io/026f985 
119.94 ms