tx · GrGUdxUZXa6N7BzJdnADKJWrDSVWHXZUJrzemqzRXe3V

3MqtTwie8XKCcUcntgFAFYnfLEnffezju4Y:  -1.40000000 Waves

2019.08.20 11:49 [639232] smart account 3MqtTwie8XKCcUcntgFAFYnfLEnffezju4Y > SELF 0.00000000 Waves

{ "type": 13, "id": "GrGUdxUZXa6N7BzJdnADKJWrDSVWHXZUJrzemqzRXe3V", "fee": 140000000, "feeAssetId": null, "timestamp": 1566290996975, "version": 1, "sender": "3MqtTwie8XKCcUcntgFAFYnfLEnffezju4Y", "senderPublicKey": "Gf4eU8JJaQziR7AfnST6tmzhUgFmeKavkwyoceen3PK1", "proofs": [ "4b87vfkQsWj9VzYRs8HFZ3nVNzVkZEYGZQVm963mYw2HZettoeC48G22PikzbUUhr46L9gb8dkYMuhLBy6pFFprg" ], "script": "base64:AwQAAAAHUHViS2V5MQEAAAAgaQxxSAhSITOlMYdvwKcfK7u/x0yzOg/68EH0ax0QlWUEAAAAB1B1YktleTIBAAAAILb58FcZXTIbjEshMW6ayDB2XcNop87YatlbtNE8j6N0BAAAAARzaWcxAwkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAFAAAAB1B1YktleTEAAAAAAAAAAAEAAAAAAAAAAAAEAAAABHNpZzIDCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAQUAAAAHUHViS2V5MgAAAAAAAAAAAQAAAAAAAAAAAAkAAGYAAAACCQAAZAAAAAIFAAAABHNpZzEFAAAABHNpZzIAAAAAAAAAAADO+UOI", "chainId": 84, "height": 639232, "spentComplexity": 0 } View: original | compacted Prev: Gfa99MNQTsgix7d43VeDub1LHuUb4LS1GZShfUXxF81s Next: 4WdfEgtFbAgQpQfuuFfDW8xumfuPemsABnPnD5DMoJnc Full:
OldNewDifferences
11 {-# STDLIB_VERSION 3 #-}
2-{-# SCRIPT_TYPE ACCOUNT #-}
3-{-# CONTENT_TYPE DAPP #-}
4-let RSAPUBLIC = fromBase64String("base64:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqlAiANSmBpDHYKP9sKgeN/l1bAb28g/tGlgDkwT5FiMN4X3pwdvdxE7mvSR8/41dU9rx4jG+6tZpb1ULVDPs431tR2IRaTXw5Cj+Ac2vhL+5JamCerGD1UW+bh/EGQtxo8W3YLDrofXB5QHJx4Pkz2Kgf+oS/C8hHuB/U4krO76U0507GTjZPP9kRQ0uLSMeqQXt8wXS+nMp5wajqxPpDLMaSREgsKwv/AEkP4dzpTYbikLBYl4qtdJsD84HLFSkiwd3BhcOrPjoIYmLxQuBD5TIMKTKD3sdZgaY9rsyqx3A00innyxD6zp3b4gFpUOX8JxKZdEC2myEqleNgg7GzwIDAQAB")
5-
6-let SERVER = addressFromStringValue("3NCiG28LmWyTigWG13E5QnvdHBsZFYXSS2j")
7-
8-let WAVELET = ((100 * 1000) * 1000)
9-
10-let SESSIONIDFIXSIZE = 44
11-
12-let RANDCYCLEPRICE = ((5 * WAVELET) / 1000)
13-
14-let MAXRANDSPERCYCLE = 14
15-
16-let STATEINIT = "INIT"
17-
18-let DATADONE = "READY"
19-
20-let STATEFINISHED = "FINISHED"
21-
22-let IdxState = 0
23-
24-let IdxOrganizerPub = 1
25-
26-let IdxRandFrom = 2
27-
28-let IdxRandTo = 3
29-
30-let IdxRandsCount = 4
31-
32-let IdxRemainRandsCount = 5
33-
34-let IdxDataKeysCount = 6
35-
36-let IdxDataDoneTxId = 7
37-
38-let IdxLastOffset = 8
39-
40-let IdxCurrRands = 13
41-
42-func abs (val) = if ((0 > val))
43- then -(val)
44- else val
45-
46-
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)
49- if ((randOrEmpty == ""))
50- then ((fullStateStr + "_") + "-")
51- else ((fullStateStr + "_") + randOrEmpty)
52- }
53-
54-
55-func extractGameDataList (sessionId) = {
56- let rawDataStr = getStringValue(this, sessionId)
57- split(rawDataStr, "_")
58- }
59-
60-
61-func nextRand (div,min,currRandsStr,remainingRands,remainingHash) = {
62- let nextRandInt = ((abs(toInt(remainingHash)) % div) + min)
63- let nextRandStr = toString(nextRandInt)
64- let duplicate = isDefined(indexOf(currRandsStr, nextRandStr))
65- if (if (!(duplicate))
66- then (remainingRands > 0)
67- else false)
68- then [((currRandsStr + "-") + nextRandStr), "yes"]
69- else [currRandsStr, ""]
70- }
71-
72-
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))
86- let div = ((to - from) + 1)
87- let rand1 = nextRand(div, from, currRandsStr, remainingRands, drop(randHash, newOffsetBytes))
88- let rem1 = if ((rand1[1] != ""))
89- then (remainingRands - 1)
90- else remainingRands
91- let rand2 = nextRand(div, from, rand1[0], rem1, drop(randHash, (newOffsetBytes + 1)))
92- let rem2 = if ((rand2[1] != ""))
93- then (rem1 - 1)
94- else rem1
95- let rand3 = nextRand(div, from, rand2[0], rem2, drop(randHash, (newOffsetBytes + 2)))
96- let rem3 = if ((rand3[1] != ""))
97- then (rem2 - 1)
98- else rem2
99- let rand4 = nextRand(div, from, rand3[0], rem3, drop(randHash, (newOffsetBytes + 3)))
100- let rem4 = if ((rand4[1] != ""))
101- then (rem3 - 1)
102- else rem3
103- let rand5 = nextRand(div, from, rand4[0], rem4, drop(randHash, (newOffsetBytes + 4)))
104- let rem5 = if ((rand5[1] != ""))
105- then (rem4 - 1)
106- else rem4
107- let rand6 = nextRand(div, from, rand5[0], rem5, drop(randHash, (newOffsetBytes + 5)))
108- let rem6 = if ((rand6[1] != ""))
109- then (rem5 - 1)
110- else rem5
111- let rand7 = nextRand(div, from, rand6[0], rem6, drop(randHash, (newOffsetBytes + 6)))
112- let rem7 = if ((rand7[1] != ""))
113- then (rem6 - 1)
114- else rem6
115- let rand8 = nextRand(div, from, rand7[0], rem7, drop(randHash, (newOffsetBytes + 7)))
116- let rem8 = if ((rand8[1] != ""))
117- then (rem7 - 1)
118- else rem7
119- let rand9 = nextRand(div, from, rand8[0], rem8, drop(randHash, (newOffsetBytes + 8)))
120- let rem9 = if ((rand9[1] != ""))
121- then (rem8 - 1)
122- else rem8
123- let rand10 = nextRand(div, from, rand9[0], rem9, drop(randHash, (newOffsetBytes + 9)))
124- let rem10 = if ((rand10[1] != ""))
125- then (rem9 - 1)
126- else rem9
127- let rand11 = nextRand(div, from, rand10[0], rem10, drop(randHash, (newOffsetBytes + 10)))
128- let rem11 = if ((rand11[1] != ""))
129- then (rem10 - 1)
130- else rem10
131-[rand11[0], if ((rem11 == 0))
132- then "0"
133- else toString(rem11), toString((newOffsetBytes + 10)), toString(newSlowIdx1), toString(newSlowIdx2), toString(newFastIdx1), toString(newFastIdx2)]
134- }
135-
136-
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 31250 but actualNum=") + keyPostfix))
169- }
170- }
171- }
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- }
201-
202-
203-@Callable(i)
204-func initDraw (randFrom,randTo,randsCount) = {
205- 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))
212- if (if ((0 >= randFrom))
213- then true
214- else (0 >= randTo))
215- then throw("randFrom and randTo must be greater than 0")
216- else if ((randFrom >= randTo))
217- then throw("randFrom must be strict less then randTo")
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 = ((((WAVELET * 1) / 1000) * 33) + ((WAVELET * 4) / 1000))
229- let randsPmt = validateAndGetRandsPmt(randsCount, pmt, minDataPmt)
230- let dataPmt = (pmt.amount - randsPmt)
231- let dataTxCount = (dataPmt / minDataPmt)
232- let dataKeysCount = if ((31250 >= (dataTxCount * 5)))
233- then (dataTxCount * 5)
234- else 31250
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- }
240- }
241-
242-
243-
244-@Callable(i)
245-func ready (sessionId) = {
246- let drawParamsList = extractGameDataList(sessionId)
247- let drawState = drawParamsList[IdxState]
248- let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
249- let randsCountStr = drawParamsList[IdxRandsCount]
250- let remainRandsCountStr = drawParamsList[IdxRemainRandsCount]
251- let fromStr = drawParamsList[IdxRandFrom]
252- let toStr = drawParamsList[IdxRandTo]
253- let dataKeysCount = drawParamsList[IdxDataKeysCount]
254- let organizerPubKey = fromBase58String(organizerPubKey58)
255- if ((drawState != STATEINIT))
256- then throw((sessionId + " draw: moving into READY state is allowed only from INIT state"))
257- else if ((organizerPubKey != i.callerPublicKey))
258- then throw((sessionId + "draw: moving into READY state is allowed for organizer only"))
259- else {
260- let readyState = formatStateDataStr(DATADONE, organizerPubKey58, fromStr, toStr, randsCountStr, remainRandsCountStr, dataKeysCount, toBase58String(i.transactionId), "0", "0", "1", "0", "1", "")
261- WriteSet([DataEntry(sessionId, readyState)])
262- }
263- }
264-
265-
266-
267-@Callable(i)
268-func random (sessionId,rsaSign) = {
269- let drawParamsList = extractGameDataList(sessionId)
270- let drawState = drawParamsList[IdxState]
271- let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
272- let randsCountStr = drawParamsList[IdxRandsCount]
273- let remainRandsCount = parseIntValue(drawParamsList[IdxRemainRandsCount])
274- let lastOffsetBytes = parseIntValue(drawParamsList[IdxLastOffset])
275- let currRandsStr = drawParamsList[IdxCurrRands]
276- let fromStr = drawParamsList[IdxRandFrom]
277- let toStr = drawParamsList[IdxRandTo]
278- 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])
283- let from = parseIntValue(fromStr)
284- let to = parseIntValue(toStr)
285- let organizerPubKey = fromBase58String(organizerPubKey58)
286- if ((drawState != DATADONE))
287- then throw((sessionId + " draw: it must be in READY state to generate random numbers"))
288- else if (!(rsaVerify(SHA256, (toBytes(sessionId) + toBytes(dataDoneTxId)), rsaSign, RSAPUBLIC)))
289- then throw("Invalid RSA signature")
290- else {
291- let randGenInfo = generateRand(sessionId, from, to, rsaSign, currRandsStr, remainRandsCount, lastOffsetBytes, slowIdx1, slowIdx2, fastIdx1, fastIdx2)
292- let newRemainRandsCountStr = randGenInfo[1]
293- let newState = if ((newRemainRandsCountStr == "0"))
294- then STATEFINISHED
295- else DATADONE
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]))])
297- }
298- }
299-
300-
301-@Verifier(tx)
302-func verify () = match tx {
303- case dtx: DataTransaction =>
304- let data0 = dtx.data[0]
305- let sessionId = take(data0.key, SESSIONIDFIXSIZE)
306- let drawParamsList = extractGameDataList(sessionId)
307- let drawState = drawParamsList[IdxState]
308- let organizerPubKey58 = drawParamsList[IdxOrganizerPub]
309- let dataKeysCount = parseIntValue(drawParamsList[IdxDataKeysCount])
310- let organizerPubKey = fromBase58String(organizerPubKey58)
311- let dataEntriesCount = size(dtx.data)
312- let allowedDataEntriesCount = 5
313- let allowedDtxSize = (32 * 1024)
314- let sigValid = sigVerify(tx.bodyBytes, tx.proofs[0], organizerPubKey)
315- let dataSizeValid = (dataEntriesCount == allowedDataEntriesCount)
316- let minDataPmt = ((((WAVELET * 1) / 1000) * 33) + ((WAVELET * 4) / 1000))
317- let feeValid = (dtx.fee == minDataPmt)
318- let keysValid = if (if (if (if (validateDtxKey(sessionId, dataKeysCount, data0))
319- then validateDtxKey(sessionId, dataKeysCount, dtx.data[1])
320- else false)
321- then validateDtxKey(sessionId, dataKeysCount, dtx.data[2])
322- else false)
323- then validateDtxKey(sessionId, dataKeysCount, dtx.data[3])
324- else false)
325- then validateDtxKey(sessionId, dataKeysCount, dtx.data[4])
326- else false
327- let dtxSizeValid = (allowedDtxSize >= size(dtx.bodyBytes))
328- if ((drawState != STATEINIT))
329- then throw(((("Data transaction is allowed for " + STATEINIT) + " status only, current status is ") + drawState))
330- else if (!(sigValid))
331- then throw("Invalid data transaction signature")
332- else if (!(feeValid))
333- then throw(("Invalid DataTransaction fee. Fee must be exact " + toString(minDataPmt)))
334- else if (!(dataSizeValid))
335- then throw(("Invalid data entries count. Data entries count must be exact " + toString(allowedDataEntriesCount)))
336- else if (!(keysValid))
337- then throw("Invalid data keys format")
338- else if (!(dtxSizeValid))
339- then throw((("Invalid DataTransaction size. Max allowed size is " + toString(allowedDtxSize)) + " bytes"))
340- else true
341- case sstx: SetScriptTransaction =>
342- true
343- case ttx: TransferTransaction =>
344- true
345- case _ =>
346- false
347-}
348-
2+{-# CONTENT_TYPE EXPRESSION #-}
3+let PubKey1 = base58'854p8BYzrj6yBPRPmfQur3oF1Rjc1AJ548qRp5FT5kDa'
4+let PubKey2 = base58'DKGFPozLrsiR8NM4NJzqQaBYC8NyGYjuw2hDYicQVjco'
5+let sig1 = if (sigVerify(tx.bodyBytes, tx.proofs[0], PubKey1))
6+ then 1
7+ else 0
8+let sig2 = if (sigVerify(tx.bodyBytes, tx.proofs[1], PubKey2))
9+ then 1
10+ else 0
11+((sig1 + sig2) > 0)

github/deemru/w8io/3ef1775 
62.95 ms