tx · 3RcHvbUrvhacUkEbDF6sAbEsJWivQptXXP9H9oenS514 3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf: -0.04300000 Waves 2024.10.24 11:06 [3340644] smart account 3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf > SELF 0.00000000 Waves
{ "type": 13, "id": "3RcHvbUrvhacUkEbDF6sAbEsJWivQptXXP9H9oenS514", "fee": 4300000, "feeAssetId": null, "timestamp": 1729757216282, "version": 2, "chainId": 84, "sender": "3Msx4Aq69zWUKy4d1wyKnQ4ofzEDAfv5Ngf", "senderPublicKey": "62i1XasxLi9NJmrEaq9UaHEGfZaonGKUL6EmFaA7gosh", "proofs": [ "3UoCkntvwb91wNJQrbPZKM8iKw7nth7gjRngRHtxk4BKKjAJHEbFqQxAR2o2xqNgyWtnoyY5xMEEEPPz6sqDRRYT" ], "script": "base64:CAJCCAISBwoFCAgCCAESBwoFCAgCCAESCAoGCAgCAQgBEgYKBAgICAESAwoBCBIAEgMKAQgSBgoECBIBARIGCgQIAQgBTQAHSU5UX01BWAD//////////38ABVdBVkVTAIDC1y8AC01JTl9CQUxBTkNFCQBoAgCgnAEFBVdBVkVTAANTRVACASwAD0JMT0NLX0hBU0hfU0laRQAgABRQVUJMSUNfS0VZX0hBU0hfU0laRQAUAA5ST09UX0hBU0hfU0laRQAgABRXSVRIRFJBV19QUk9PRlNfU0laRQAKABRFVEhfQUREUkVTU19TVFJfU0laRQAoABZNQVhfQ0xfVE9fRUxfVFJBTlNGRVJTABAACXplcm9lc1N0cgKACDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAC29mZnNldHNfMTAwCQC8CQICZDo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjoCAAAMYWxsTWluZXJzS2V5AglhbGxNaW5lcnMADm1haW5DaGFpbklkS2V5AgttYWluQ2hhaW5JZAAObGFzdENoYWluSWRLZXkCC2xhc3RDaGFpbklkABdmaXJzdFZhbGlkQWx0Q2hhaW5JZEtleQIUZmlyc3RWYWxpZEFsdENoYWluSWQADm1pbmVyUmV3YXJkS2V5AgttaW5lclJld2FyZAAKYmxvY2tNZXRhSwIIYmxvY2tfMHgAEWZpbmFsaXplZEJsb2NrS2V5Ag5maW5hbGl6ZWRCbG9jawAKdG9rZW5JZEtleQIHdG9rZW5JZAASZWxCcmlkZ2VBZGRyZXNzS2V5Ag9lbEJyaWRnZUFkZHJlc3MAF25hdGl2ZVRyYW5zZmVyc0NvdW50S2V5AhRuYXRpdmVUcmFuc2ZlcnNDb3VudAANZGFvQWRkcmVzc0tleQIKZGFvQWRkcmVzcwAMZGFvUmV3YXJkS2V5AglkYW9SZXdhcmQBA3BhZAEBaQQBcwkApAMBBQFpBAckbWF0Y2gwCQCxAgEFAXMDCQAAAgABBQckbWF0Y2gwCQCsAgICBzAwMDAwMDAFAXMDCQAAAgACBQckbWF0Y2gwCQCsAgICBjAwMDAwMAUBcwMJAAACAAMFByRtYXRjaDAJAKwCAgIFMDAwMDAFAXMDCQAAAgAEBQckbWF0Y2gwCQCsAgICBDAwMDAFAXMDCQAAAgAFBQckbWF0Y2gwCQCsAgICAzAwMAUBcwMJAAACAAYFByRtYXRjaDAJAKwCAgICMDAFAXMDCQAAAgAHBQckbWF0Y2gwCQCsAgICATAFAXMFAXMBFGJsb2NrRTJDVHJhbnNmZXJzS2V5AQxibG9ja0hhc2hIZXgJAKwCAgISZWxUb0NsVHJhbnNmZXJzXzB4BQxibG9ja0hhc2hIZXgBDGVwb2NoTWV0YUtleQEFZXBvY2gJAKwCAgIGZXBvY2hfCQEDcGFkAQUFZXBvY2gBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQdjaGFpbklkCQCsAgIJAKwCAgIFY2hhaW4JAKQDAQUHY2hhaW5JZAIKRmlyc3RCbG9jawEMY2hhaW5NZXRhS2V5AQdjaGFpbklkCQCsAgICBmNoYWluXwkBA3BhZAEFB2NoYWluSWQBEmNoYWluTGFzdEhlaWdodEtleQIHY2hhaW5JZAVtaW5lcgkArAICCQCsAgIJAKwCAgIGY2hhaW5fCQEDcGFkAQUHY2hhaW5JZAIBXwkApQgBBQVtaW5lcgEUY2hhaW5Gb3JrZWRIZWlnaHRLZXkBB2NoYWluSWQJAKwCAgkArAICAgZjaGFpbl8JAQNwYWQBBQdjaGFpbklkAgxGb3JrZWRIZWlnaHQBDXN1cHBvcnRlcnNLZXkBB2NoYWluSWQJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgpTdXBwb3J0ZXJzARVtaW5lclJld2FyZEFkZHJlc3NLZXkBCW1pbmVyQWRkcgkArAICCQCsAgICBm1pbmVyXwUJbWluZXJBZGRyAg5fUmV3YXJkQWRkcmVzcwEKbWluZXJQa0tleQENcmV3YXJkQWRkcmVzcwkArAICCQCsAgICCG1pbmVyXzB4BQ1yZXdhcmRBZGRyZXNzAgNfUEsBD21pbmVyQ2hhaW5JZEtleQEFbWluZXIJAKwCAgkArAICAgZtaW5lcl8JAKUIAQUFbWluZXICCF9DaGFpbklkABRuYXRpdmVUcmFuc2ZlcnNDb3VudAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBRduYXRpdmVUcmFuc2ZlcnNDb3VudEtleQAAARFuYXRpdmVUcmFuc2ZlcktleQEFaW5kZXgJAKwCAgIPbmF0aXZlVHJhbnNmZXJfCQCkAwEFBWluZGV4ARVta05hdGl2ZVRyYW5zZmVyRW50cnkDBWluZGV4EGRlc3RFbEFkZHJlc3NIZXgGYW1vdW50CQELU3RyaW5nRW50cnkCCQERbmF0aXZlVHJhbnNmZXJLZXkBBQVpbmRleAkArAICCQCsAgIJAKwCAgICMHgFEGRlc3RFbEFkZHJlc3NIZXgFA1NFUAkApAMBBQZhbW91bnQBFmVuc3VyZUNvcnJlY3RUcmFuc2ZlcnMDEHJlZlRyYW5zZmVySW5kZXgNdHJhbnNmZXJJbmRleAxleHBlY3RSZXdhcmQEDG1heFRyYW5zZmVycwMFDGV4cGVjdFJld2FyZAkAZQIFFk1BWF9DTF9UT19FTF9UUkFOU0ZFUlMAAQUWTUFYX0NMX1RPX0VMX1RSQU5TRkVSUwQPYWN0dWFsVHJhbnNmZXJzCQBlAgUNdHJhbnNmZXJJbmRleAUQcmVmVHJhbnNmZXJJbmRleAQLY2hlY2tOdW1iZXIDCQBmAgUPYWN0dWFsVHJhbnNmZXJzBQxtYXhUcmFuc2ZlcnMJAAIBCQCsAgIJAKwCAgkArAICAg1BbGxvd2VkIG9ubHkgCQCkAwEFDG1heFRyYW5zZmVycwIQIHRyYW5zZmVycywgZ290IAkApAMBBQ9hY3R1YWxUcmFuc2ZlcnMGAwkAAAIFC2NoZWNrTnVtYmVyBQtjaGVja051bWJlcgMJAGcCBQ10cmFuc2ZlckluZGV4BRRuYXRpdmVUcmFuc2ZlcnNDb3VudAkAAgEJAKwCAgkArAICCQCsAgICFUF0dGVtcHQgdG8gdHJhbnNmZXIgIwkApAMBBQ10cmFuc2ZlckluZGV4AhcuIEF2YWlsYWJsZSB0cmFuc2ZlcnM6IAkApAMBBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAYJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BCmFtb3VudEd0RXEDAXQEZ3RFcQlxdWV1ZVNpemUDCQBnAggFAXQGYW1vdW50BQRndEVxBgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFFRyYW5zZmVycmluZyBhbW91bnQgCQCkAwEIBQF0BmFtb3VudAIOIHNob3VsZCBiZSA+PSAJAKQDAQUEZ3RFcQITIGZvciBxdWV1ZSBzaXplIG9mIAkApAMBBQlxdWV1ZVNpemUCFy4gVHJhbnNmZXIgbW9yZSBvciB3YWl0ARFnZW5lcmF0aW5nQmFsYW5jZQEHYWRkcmVzcwgJAO8HAQUHYWRkcmVzcwpnZW5lcmF0aW5nAQljaGFpbk1ldGEBB2NoYWluSWQEAXMJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkBAVpdGVtcwkAtQkCBQFzBQNTRVAJAJQKAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWl0ZW1zAAAJAJEDAgUFaXRlbXMAAQEQbWtDaGFpbk1ldGFFbnRyeQMHY2hhaW5JZA5uZXdDaGFpbkhlaWdodAxibG9ja0hhc2hIZXgJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgAC21haW5DaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDm1haW5DaGFpbklkS2V5AAAACyR0MDUyNDk1MzE1CQEJY2hhaW5NZXRhAQULbWFpbkNoYWluSWQAD21haW5DaGFpbkhlaWdodAgFCyR0MDUyNDk1MzE1Al8xABJtYWluQ2hhaW5MYXN0QmxvY2sIBQskdDA1MjQ5NTMxNQJfMgEJZXBvY2hNZXRhAQVlcG9jaAQHJG1hdGNoMAkAoggBCQEMZXBvY2hNZXRhS2V5AQUFZXBvY2gDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBAlmcmFnbWVudHMJALUJAgUBcwUDU0VQCQCVCgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUJZnJhZ21lbnRzAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmcmFnbWVudHMAAQkAkQMCBQlmcmFnbWVudHMAAgUEdW5pdAALJHQwNTU0NjU2NzAEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIWKEFkZHJlc3MsIEludCwgU3RyaW5nKQQBbQUHJG1hdGNoMAUBbQkAlAoCBQR1bml0AAAADnRoaXNFcG9jaE1pbmVyCAULJHQwNTU0NjU2NzACXzEADHRoaXNFcG9jaFJlZggFCyR0MDU1NDY1NjcwAl8yAAxhbGxNaW5lcnNTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUMYWxsTWluZXJzS2V5AgAACWFsbE1pbmVycwQHJG1hdGNoMAUMYWxsTWluZXJzU3RyAwkAAAICAAUHJG1hdGNoMAUDbmlsAwkAAQIFByRtYXRjaDACBlN0cmluZwQDcmF3BQckbWF0Y2gwCQC8CQIFA3JhdwUDU0VQCQACAQILTWF0Y2ggZXJyb3IBCWJsb2NrTWV0YQEHYmxvY2tJZAQEbWV0YQkBEUBleHRyTmF0aXZlKDEwNTcpAQkArAICBQpibG9ja01ldGFLBQdibG9ja0lkBAhtZXRhU2l6ZQkAyAEBBQRtZXRhBAtibG9ja0hlaWdodAkAsQkBBQRtZXRhBApibG9ja0Vwb2NoCQCyCQIFBG1ldGEACAQLYmxvY2tQYXJlbnQJAMkBAgkAygECBQRtZXRhABAFD0JMT0NLX0hBU0hfU0laRQQHY2hhaW5JZAkAsgkCBQRtZXRhCQBkAgAQBQ9CTE9DS19IQVNIX1NJWkUECmJhc2VPZmZzZXQJAGQCABgFD0JMT0NLX0hBU0hfU0laRQQOcmVtYWluaW5nQnl0ZXMJAGUCBQhtZXRhU2l6ZQUKYmFzZU9mZnNldAQUZTJjVHJhbnNmZXJzUm9vdEhhc2gDCQBnAgUOcmVtYWluaW5nQnl0ZXMFDlJPT1RfSEFTSF9TSVpFCQDJAQIJAMoBAgUEbWV0YQUKYmFzZU9mZnNldAUOUk9PVF9IQVNIX1NJWkUBAAQUbGFzdEMyRVRyYW5zZmVySW5kZXgDAwkAAAIFDnJlbWFpbmluZ0J5dGVzAAgGCQBmAgUOcmVtYWluaW5nQnl0ZXMFDlJPT1RfSEFTSF9TSVpFCQCyCQIFBG1ldGEJAGQCBQpiYXNlT2Zmc2V0CQDIAQEFFGUyY1RyYW5zZmVyc1Jvb3RIYXNoAP///////////wEJAJgKBgULYmxvY2tIZWlnaHQFCmJsb2NrRXBvY2gFC2Jsb2NrUGFyZW50BQdjaGFpbklkBRRlMmNUcmFuc2ZlcnNSb290SGFzaAUUbGFzdEMyRVRyYW5zZmVySW5kZXgBEG1rQmxvY2tNZXRhRW50cnkGDGJsb2NrSGFzaEhleAtibG9ja0hlaWdodA5ibG9ja1BhcmVudEhleAdjaGFpbklkF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4FGxhc3RDMkVUcmFuc2ZlckluZGV4BBllMmNUcmFuc2ZlcnNSb290SGFzaEJ5dGVzCQDdBAEFF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4BBFyb290SGFzaEJ5dGVzU2l6ZQkAyAEBBRllMmNUcmFuc2ZlcnNSb290SGFzaEJ5dGVzBA1jaGVja1Jvb3RIYXNoAwMJAAACBRFyb290SGFzaEJ5dGVzU2l6ZQAABgkAAAIFEXJvb3RIYXNoQnl0ZXNTaXplBQ5ST09UX0hBU0hfU0laRQYJAAIBCQCsAgIJAKwCAgkArAICAiVUcmFuc2ZlcnMgcm9vdCBoYXNoIHNob3VsZCBoYXZlIDAgb3IgCQCkAwEFDlJPT1RfSEFTSF9TSVpFAgwgYnl0ZXMsIGdvdCAJAKQDAQURcm9vdEhhc2hCeXRlc1NpemUDCQAAAgUNY2hlY2tSb290SGFzaAUNY2hlY2tSb290SGFzaAQOYmxvY2tNZXRhQnl0ZXMJAMsBAgkAywECCQDLAQIJAMsBAgkAywECCQCaAwEFC2Jsb2NrSGVpZ2h0CQCaAwEFBmhlaWdodAkA3QQBBQ5ibG9ja1BhcmVudEhleAkAmgMBBQdjaGFpbklkBRllMmNUcmFuc2ZlcnNSb290SGFzaEJ5dGVzCQCaAwEFFGxhc3RDMkVUcmFuc2ZlckluZGV4CQELQmluYXJ5RW50cnkCCQCsAgIFCmJsb2NrTWV0YUsFDGJsb2NrSGFzaEhleAUOYmxvY2tNZXRhQnl0ZXMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BDGxhc3RIZWlnaHRCeQIFbWluZXIHY2hhaW5JZAQHJG1hdGNoMAkAnwgBCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAUFbWluZXIDCQABAgUHJG1hdGNoMAIDSW50BAFoBQckbWF0Y2gwBQFoBAlibG9ja0hhc2gJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAKwCAgkArAICCQCsAgICBWNoYWluCQCkAwEFB2NoYWluSWQCC0xhc3RNaW5lZEJ5CQClCAEFBW1pbmVyCAkBCWJsb2NrTWV0YQEFCWJsb2NrSGFzaAJfMQALJHQwNzcxMDg2NDUECWhpdFNvdXJjZQQHJG1hdGNoMAgFCWxhc3RCbG9jawN2cmYDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQDdnJmBQckbWF0Y2gwBQN2cmYIBQlsYXN0QmxvY2sTZ2VuZXJhdGlvblNpZ25hdHVyZQoBDHByb2Nlc3NNaW5lcgIEcHJldgVtaW5lcgQLJHQwNzk3NzgwNDAFBHByZXYECXByZXZNaW5lcggFCyR0MDc5Nzc4MDQwAl8xBBBwcmV2VG90YWxCYWxhbmNlCAULJHQwNzk3NzgwNDACXzIECXByZXZEZWxheQgFCyR0MDc5Nzc4MDQwAl8zBApwcmV2TWluZXJzCAULJHQwNzk3NzgwNDACXzQEDG1pbmVyQWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNjIpAQUFbWluZXIED3dhdmVzR2VuQmFsYW5jZQgJAO8HAQUMbWluZXJBZGRyZXNzCmdlbmVyYXRpbmcEDG1pbmVyQmFsYW5jZQkBEWdlbmVyYXRpbmdCYWxhbmNlAQUMbWluZXJBZGRyZXNzAwMJAGYCBQtNSU5fQkFMQU5DRQUPd2F2ZXNHZW5CYWxhbmNlBgkAZwIAAAUMbWluZXJCYWxhbmNlBQRwcmV2BAluZXh0RGVsYXkJAIUHAgUMbWluZXJBZGRyZXNzBQxtaW5lckJhbGFuY2UDCQBmAgUJcHJldkRlbGF5BQluZXh0RGVsYXkJAJYKBAUFbWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UFCW5leHREZWxheQkAzQgCBQpwcmV2TWluZXJzBQVtaW5lcgkAlgoEBQlwcmV2TWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UFCXByZXZEZWxheQkAzQgCBQpwcmV2TWluZXJzBQVtaW5lcgoAAiRsBQlhbGxNaW5lcnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCWCgQCAAAABQdJTlRfTUFYBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDHByb2Nlc3NNaW5lcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgNTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyABFjb21wdXRlZEdlbmVyYXRvcggFCyR0MDc3MTA4NjQ1Al8xABRjb21wdXRlZFRvdGFsQmFsYW5jZQgFCyR0MDc3MTA4NjQ1Al8yAAskdDA4NjQ3ODcxMwkBCWJsb2NrTWV0YQEFEm1haW5DaGFpbkxhc3RCbG9jawAMbWNsYklnbm9yZWQxCAULJHQwODY0Nzg3MTMCXzEADm1haW5DaGFpbkVwb2NoCAULJHQwODY0Nzg3MTMCXzIBI2NhbGN1bGF0ZUZpbmFsaXplZEJsb2NrSGFzaEFuZEVwb2NoAwhjdXJNaW5lcgxjdXJQcmV2RXBvY2gQY3VyTGFzdEJsb2NrSGFzaAQLaGFsZkJhbGFuY2UJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACCgEEc3RlcAIEcHJldgRuZXh0BAskdDA4OTUxOTAyNAUEcHJldgQJdGhpc0Vwb2NoCAULJHQwODk1MTkwMjQCXzEEF21heWJlRmluYWxpemVkQmxvY2tIYXNoCAULJHQwODk1MTkwMjQCXzIEDHRvdGFsQmFsYW5jZQgFCyR0MDg5NTE5MDI0Al8zBApwcmV2TWluZXJzCAULJHQwODk1MTkwMjQCXzQEByRtYXRjaDAFF21heWJlRmluYWxpemVkQmxvY2tIYXNoAwkAAQIFByRtYXRjaDACBFVuaXQECyR0MDkwOTE5MjU3AwkAAAIFCXRoaXNFcG9jaAUGaGVpZ2h0CQCVCgMFCGN1ck1pbmVyBQxjdXJQcmV2RXBvY2gFEGN1ckxhc3RCbG9ja0hhc2gJAQV2YWx1ZQEJAQllcG9jaE1ldGEBBQl0aGlzRXBvY2gEBW1pbmVyCAULJHQwOTA5MTkyNTcCXzEECXByZXZFcG9jaAgFCyR0MDkwOTE5MjU3Al8yBA1sYXN0QmxvY2tIYXNoCAULJHQwOTA5MTkyNTcCXzMDAwkAAAIFCXByZXZFcG9jaAAABgkAZwIJAGUCBQZoZWlnaHQFCXRoaXNFcG9jaABkCQCWCgQFCXRoaXNFcG9jaAUNbGFzdEJsb2NrSGFzaAUMdG90YWxCYWxhbmNlBQlhbGxNaW5lcnMECyR0MDk0MTE5NjEzAwkBD2NvbnRhaW5zRWxlbWVudAIFCnByZXZNaW5lcnMFBW1pbmVyCQCUCgIFDHRvdGFsQmFsYW5jZQUKcHJldk1pbmVycwkAlAoCCQBkAgUMdG90YWxCYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQVtaW5lcgkAzAgCBQVtaW5lcgUKcHJldk1pbmVycwQPbmV3VG90YWxCYWxhbmNlCAULJHQwOTQxMTk2MTMCXzEECW5ld01pbmVycwgFCyR0MDk0MTE5NjEzAl8yAwkAZgIFD25ld1RvdGFsQmFsYW5jZQULaGFsZkJhbGFuY2UJAJYKBAUJdGhpc0Vwb2NoBQ1sYXN0QmxvY2tIYXNoBQ9uZXdUb3RhbEJhbGFuY2UFCWFsbE1pbmVycwkAlgoEBQlwcmV2RXBvY2gFBHVuaXQFD25ld1RvdGFsQmFsYW5jZQUJbmV3TWluZXJzBQRwcmV2BAskdDA5ODQ2OTk0MwoAAiRsBQtvZmZzZXRzXzEwMAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJYKBAUGaGVpZ2h0BQR1bml0AAAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEc3RlcAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIVTGlzdCBzaXplIGV4Y2VlZHMgMTAwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAYgBjAGQEDmZpbmFsaXplZEVwb2NoCAULJHQwOTg0Njk5NDMCXzEEFWZpbmFsaXplZEJsb2NrSGFzaE9wdAgFCyR0MDk4NDY5OTQzAl8yCQCUCgIEByRtYXRjaDAFFWZpbmFsaXplZEJsb2NrSGFzaE9wdAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEEmZpbmFsaXplZEJsb2NrSGFzaAUHJG1hdGNoMAUSZmluYWxpemVkQmxvY2tIYXNoCAkBBXZhbHVlAQkBCWVwb2NoTWV0YQEFDmZpbmFsaXplZEVwb2NoAl8zBQ5maW5hbGl6ZWRFcG9jaAERc3VwcG9ydGluZ0JhbGFuY2UBB2NoYWluSWQKAQphZGRCYWxhbmNlAgNhY2MMZ2VuZXJhdG9yU3RyBA0kdDAxMDIyNjEwMjYyBQNhY2MEDHRvdGFsQmFsYW5jZQgFDSR0MDEwMjI2MTAyNjICXzEECmdlbmVyYXRvcnMIBQ0kdDAxMDIyNjEwMjYyAl8yBAlnZW5lcmF0b3IJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDGdlbmVyYXRvclN0cgMJAQ9jb250YWluc0VsZW1lbnQCBQpnZW5lcmF0b3JzBQlnZW5lcmF0b3IFA2FjYwQHYmFsYW5jZQkBEWdlbmVyYXRpbmdCYWxhbmNlAQUJZ2VuZXJhdG9yCQCUCgIJAGQCBQx0b3RhbEJhbGFuY2UFB2JhbGFuY2UJAM0IAgUKZ2VuZXJhdG9ycwUJZ2VuZXJhdG9yBA1hbGxHZW5lcmF0b3JzCQC8CQIJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQ1zdXBwb3J0ZXJzS2V5AQUHY2hhaW5JZAUDU0VQBANyZXMKAAIkbAUNYWxsR2VuZXJhdG9ycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAABQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCmFkZEJhbGFuY2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFUxpc3Qgc2l6ZSBleGNlZWRzIDEwMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAGIAYwBkCAUDcmVzAl8xAQ9pc0NvbnRyYWN0U2V0dXAACQEJaXNEZWZpbmVkAQkAnwgBBQ5taW5lclJld2FyZEtleQERZW5zdXJlTWluaW5nRXBvY2gBCWdlbmVyYXRvcgMJAQIhPQIJAKUIAQUJZ2VuZXJhdG9yBRFjb21wdXRlZEdlbmVyYXRvcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkA2AQBCAUJZ2VuZXJhdG9yBWJ5dGVzAhsgaXMgbm90IGFsbG93ZWQgdG8gbWluZSBpbiAJAKQDAQUGaGVpZ2h0AhEgZXBvY2guIEV4cGVjdGVkIAURY29tcHV0ZWRHZW5lcmF0b3IFBHVuaXQBEmlzUmVmZXJlbmNlQ29ycmVjdAIJcmVmZXJlbmNlCWxhc3RCbG9jawMJAAACBQlyZWZlcmVuY2UFCWxhc3RCbG9jawUEdW5pdAkAAgEJAKwCAgkArAICCQCsAgICMEV4cGVjdGVkIGEgcmVmZXJlbmNlIHRvIHRoZSBjaGFpbiBsYXN0IGJsb2NrOiAweAUJbGFzdEJsb2NrAgkuIEdvdDogMHgFCXJlZmVyZW5jZQEPY2hhaW5Jc0luYWN0aXZlAQdjaGFpbklkBAxmaXJzdEJsb2NrSWQJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEFB2NoYWluSWQEFGZpcnN0VmFsaWRBbHRDaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5AAADCQBmAgUUZmlyc3RWYWxpZEFsdENoYWluSWQFB2NoYWluSWQGCQBmAggJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMQgJAQlibG9ja01ldGEBBQxmaXJzdEJsb2NrSWQCXzEBDG1pbmVyQ2hhaW5JZAEFbWluZXIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBD21pbmVyQ2hhaW5JZEtleQEFBW1pbmVyCQCfCAEJAKwCAgIJY2hhaW5JZE9mCQClCAEFBW1pbmVyAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMJZ2VuZXJhdG9yD2V4cGVjdGVkQ2hhaW5JZBBjaGVja0hlaWdodEJsb2NrBA9oZWlnaHRJc0NvcnJlY3QEByRtYXRjaDAFEGNoZWNrSGVpZ2h0QmxvY2sDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAlibG9ja0hhc2gFByRtYXRjaDAEFGxhc3RNaW5lZEJsb2NrSGVpZ2h0CQEMbGFzdEhlaWdodEJ5AgUJZ2VuZXJhdG9yBQttYWluQ2hhaW5JZAkAZgIJAGQCCAkBCWJsb2NrTWV0YQEFCWJsb2NrSGFzaAJfMQABBRRsYXN0TWluZWRCbG9ja0hlaWdodAYEByRtYXRjaDAJAQxtaW5lckNoYWluSWQBBQlnZW5lcmF0b3IDCQABAgUHJG1hdGNoMAIDSW50BAljdXJyZW50SWQFByRtYXRjaDADAwkAAAIFCWN1cnJlbnRJZAUPZXhwZWN0ZWRDaGFpbklkBgMJAQ9jaGFpbklzSW5hY3RpdmUBBQljdXJyZW50SWQFD2hlaWdodElzQ29ycmVjdAcFBHVuaXQJAAIBCQCsAgICHG1pbmVyIGlzIG1pbmluZyBvdGhlciBjaGFpbiAJAKQDAQUJY3VycmVudElkBQR1bml0AAxoZWlnaHRTdHJpbmcJAKwCAgILIGF0IGhlaWdodCAJAKQDAQUGaGVpZ2h0AQV2cmZBdAEGaGVpZ2h0CQETdmFsdWVPckVycm9yTWVzc2FnZQIICQETdmFsdWVPckVycm9yTWVzc2FnZQIJAO0HAQUGaGVpZ2h0CQCsAgICG2xhc3QgYmxvY2sgaXMgbm90IGF2YWlsYWJsZQUMaGVpZ2h0U3RyaW5nA3ZyZgkArAICAhRWUkYgaXMgbm90IGF2YWlsYWJsZQUMaGVpZ2h0U3RyaW5nARJlbnN1cmVDb3JyZWN0RXBvY2gBC2V4cGVjdGVkVlJGBAlhY3R1YWxWUkYJAQV2cmZBdAEFBmhlaWdodAMJAAACBQtleHBlY3RlZFZSRgUJYWN0dWFsVlJGBQR1bml0CQACAQkArAICCQCsAgIJAKwCAgkArAICAg1FeHBlY3RlZCBWUkYgCQDYBAEFC2V4cGVjdGVkVlJGAhcgZG9lcyBub3QgbWF0Y2ggYWN0dWFsIAkA2AQBBQlhY3R1YWxWUkYFDGhlaWdodFN0cmluZwEMYWRkU3VwcG9ydGVyAgdjaGFpbklkCWdlbmVyYXRvcgQNc3VwcG9ydGVyc1N0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBDXN1cHBvcnRlcnNLZXkBBQdjaGFpbklkBApzdXBwb3J0ZXJzCQC8CQIFDXN1cHBvcnRlcnNTdHIFA1NFUAMJAQ9jb250YWluc0VsZW1lbnQCBQpzdXBwb3J0ZXJzCQClCAEFCWdlbmVyYXRvcgUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1zdXBwb3J0ZXJzS2V5AQUHY2hhaW5JZAkArAICCQCsAgIFDXN1cHBvcnRlcnNTdHIFA1NFUAkApQgBBQlnZW5lcmF0b3IFA25pbAEJc2V0T3JGYWlsAgVmbGFncwVpbmRleAMJAGYCAAAFBWluZGV4CQACAQkArAICAiJDYW4ndCB3aXRoZHJhdyBhdCBuZWdhdGl2ZSBpbmRleDogCQCkAwEFBWluZGV4BAlmbGFnc1NpemUJALECAQUFZmxhZ3MDCQBnAgUFaW5kZXgFCWZsYWdzU2l6ZQQJYWRkWmVyb2VzCQBlAgUFaW5kZXgFCWZsYWdzU2l6ZQMJAGYCBQlhZGRaZXJvZXMJALECAQUJemVyb2VzU3RyCQACAQkArAICCQCsAgICCkNhbid0IGFkZCAJAKQDAQUJYWRkWmVyb2VzAiUgZW1wdHkgZmxhZ3MuIENvbnRhY3Qgd2l0aCBkZXZlbG9wZXJzCQCsAgIJAKwCAgUFZmxhZ3MJAK8CAgUJemVyb2VzU3RyBQlhZGRaZXJvZXMCATEEBHRhaWwJALACAgUFZmxhZ3MFBWluZGV4BAdhdEluZGV4CQCvAgIFBHRhaWwAAQMJAAACBQdhdEluZGV4AgEwCQCsAgIJAKwCAgkArwICBQVmbGFncwUFaW5kZXgCATEJALACAgUEdGFpbAABCQACAQkArAICCQCsAgICClRyYW5zZmVyICMJAKQDAQUFaW5kZXgCFyBoYXMgYmVlbiBhbHJlYWR5IHRha2VuARF2YWxpZGF0ZUJsb2NrSGFzaAEGaGV4U3RyBAxkZWNvZGVkQnl0ZXMJAN0EAQUGaGV4U3RyAwkBAiE9AgkAyAEBBQxkZWNvZGVkQnl0ZXMFD0JMT0NLX0hBU0hfU0laRQkAAgECF2ludmFsaWQgYmxvY2sgaWQgbGVuZ3RoBQZoZXhTdHIBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwZjYWxsZXIPbmV3QmxvY2tIYXNoSGV4CXByZXZFcG9jaAQVY3VyRmluYWxpemVkQmxvY2tNZXRhCQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkEDSR0MDE0MjczMTQzOTMJASNjYWxjdWxhdGVGaW5hbGl6ZWRCbG9ja0hhc2hBbmRFcG9jaAMFBmNhbGxlcgUJcHJldkVwb2NoBQ9uZXdCbG9ja0hhc2hIZXgEFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAgFDSR0MDE0MjczMTQzOTMCXzEEEW5ld0ZpbmFsaXplZEVwb2NoCAUNJHQwMTQyNzMxNDM5MwJfMgQNcmV3YXJkQWN0aW9ucwQHJG1hdGNoMAkAoggBBQ1kYW9BZGRyZXNzS2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQEYWRkcgUHJG1hdGNoMAMJAAACBRFuZXdGaW5hbGl6ZWRFcG9jaAgFFWN1ckZpbmFsaXplZEJsb2NrTWV0YQJfMgUDbmlsCgETY291bnROb25FbXB0eUVwb2NocwIDYWNjBG5leHQDCQAAAggFA2FjYwJfMQgFFWN1ckZpbmFsaXplZEJsb2NrTWV0YQJfMgUDYWNjBAckbWF0Y2gxCQEJZXBvY2hNZXRhAQgFA2FjYwJfMQMJAAECBQckbWF0Y2gxAhYoQWRkcmVzcywgSW50LCBTdHJpbmcpBAFtBQckbWF0Y2gxCQCUCgIIBQFtAl8yCQBkAggFA2FjYwJfMgABBQNhY2MEDnN0YXJ0RnJvbUVwb2NoAwkAAAIFEW5ld0ZpbmFsaXplZEVwb2NoBQZoZWlnaHQFCXByZXZFcG9jaAgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBCWVwb2NoTWV0YQEFEW5ld0ZpbmFsaXplZEVwb2NoAhdubyBwcmV2IGVwb2NoIGZvciBzdGFydAJfMgQKZGFvUmV3YXJkcwoAAiRsBQtvZmZzZXRzXzEwMAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUOc3RhcnRGcm9tRXBvY2gAAQoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQETY291bnROb25FbXB0eUVwb2NocwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIVTGlzdCBzaXplIGV4Y2VlZHMgMTAwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAYgBjAGQEDXJlaXNzdWVBbW91bnQJAGgCCAUKZGFvUmV3YXJkcwJfMgkBEUBleHRyTmF0aXZlKDEwNTUpAQUMZGFvUmV3YXJkS2V5BAd0b2tlbklkCQDZBAEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFCnRva2VuSWRLZXkJAMwIAgkBB1JlaXNzdWUDBQd0b2tlbklkBQ1yZWlzc3VlQW1vdW50BgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEJANkEAQUEYWRkcgUNcmVpc3N1ZUFtb3VudAUHdG9rZW5JZAUDbmlsBQNuaWwJAM4IAgUNcmV3YXJkQWN0aW9ucwMDCQAAAgUVbmV3RmluYWxpemVkQmxvY2tIYXNoBQ9uZXdCbG9ja0hhc2hIZXgGCQBmAggJAQlibG9ja01ldGEBBRVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gCXzEIBRVjdXJGaW5hbGl6ZWRCbG9ja01ldGECXzEJAMwIAgkBC1N0cmluZ0VudHJ5AgURZmluYWxpemVkQmxvY2tLZXkFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAUDbmlsBQNuaWwJAWkBD2V4dGVuZE1haW5DaGFpbgUMYmxvY2tIYXNoSGV4DHJlZmVyZW5jZUhleAN2cmYXZTJjVHJhbnNmZXJzUm9vdEhhc2hIZXgUbGFzdEMyRVRyYW5zZmVySW5kZXgEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUDdnJmAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gECmNoZWNrQ2hhaW4JAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQFBHVuaXQDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQOY2hlY2tSZWZlcmVuY2UJARJpc1JlZmVyZW5jZUNvcnJlY3QCBQxyZWZlcmVuY2VIZXgFEm1haW5DaGFpbkxhc3RCbG9jawMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al82BRRsYXN0QzJFVHJhbnNmZXJJbmRleAYDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQ5tYWluQ2hhaW5FcG9jaAUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkAwkAAAIFDXRoaXNFcG9jaE1ldGEFDXRoaXNFcG9jaE1ldGEEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFDm1haW5DaGFpbkVwb2NoBA5uZXdDaGFpbkhlaWdodAkAZAIFD21haW5DaGFpbkhlaWdodAABCQDOCAIJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkGBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BRJtYWluQ2hhaW5MYXN0QmxvY2sFC21haW5DaGFpbklkBRdlMmNUcmFuc2ZlcnNSb290SGFzaEhleAUUbGFzdEMyRVRyYW5zZmVySW5kZXgJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQttYWluQ2hhaW5JZAUObmV3Q2hhaW5IZWlnaHQFDGJsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD21pbmVyQ2hhaW5JZEtleQEIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCBQ10aGlzRXBvY2hNZXRhBQNuaWwFFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDXN0YXJ0QWx0Q2hhaW4FDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgDdnJmF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4FGxhc3RDMkVUcmFuc2ZlckluZGV4BA5jaGVja0Jsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4AwkAAAIFDmNoZWNrQmxvY2tIYXNoBQ5jaGVja0Jsb2NrSGFzaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFA3ZyZgMJAAACBQpjaGVja0Vwb2NoBQpjaGVja0Vwb2NoBA0kdDAxNzI5MDE3NDAzCQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4BA5yZWZDaGFpbkhlaWdodAgFDSR0MDE3MjkwMTc0MDMCXzEECHJlZkVwb2NoCAUNJHQwMTcyOTAxNzQwMwJfMgQLcmVmSWdub3JlZDEIBQ0kdDAxNzI5MDE3NDAzAl8zBAtyZWZJZ25vcmVkMggFDSR0MDE3MjkwMTc0MDMCXzQEC3JlZklnbm9yZWQzCAUNJHQwMTcyOTAxNzQwMwJfNQQQcmVmVHJhbnNmZXJJbmRleAgFDSR0MDE3MjkwMTc0MDMCXzYEDmZpbmFsaXplZEVwb2NoCAkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFEWZpbmFsaXplZEJsb2NrS2V5Al8yBAhlcG9jaFJlZgMJAGcCBQhyZWZFcG9jaAUOZmluYWxpemVkRXBvY2gFCHJlZkVwb2NoCQACAQkArAICCQCsAgIJAKwCAgkArAICAiNDYW4gbm90IHN0YXJ0IGFsdCBjaGFpbiBmcm9tIGVwb2NoIAkApAMBBQhyZWZFcG9jaAIILCBlcG9jaCAJAKQDAQUOZmluYWxpemVkRXBvY2gCDSBpcyBmaW5hbGl6ZWQECmNoZWNrQ2hhaW4JAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQFDHJlZmVyZW5jZUhleAMJAAACBQpjaGVja0NoYWluBQpjaGVja0NoYWluBA5jaGVja1RyYW5zZmVycwkBFmVuc3VyZUNvcnJlY3RUcmFuc2ZlcnMDBRByZWZUcmFuc2ZlckluZGV4BRRsYXN0QzJFVHJhbnNmZXJJbmRleAYDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBApuZXdDaGFpbklkCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQ5sYXN0Q2hhaW5JZEtleQAAAAEEDm5ld0NoYWluSGVpZ2h0CQBkAgUOcmVmQ2hhaW5IZWlnaHQAAQQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUIZXBvY2hSZWYFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IJAMwIAgUNdGhpc0Vwb2NoTWV0YQkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQYFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFDHJlZmVyZW5jZUhleAUKbmV3Q2hhaW5JZAUXZTJjVHJhbnNmZXJzUm9vdEhhc2hIZXgFFGxhc3RDMkVUcmFuc2ZlckluZGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEFCm5ld0NoYWluSWQFDGJsb2NrSGFzaEhleAkAzAgCCQEQbWtDaGFpbk1ldGFFbnRyeQMFCm5ld0NoYWluSWQFDm5ld0NoYWluSGVpZ2h0BQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFCm5ld0NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQpuZXdDaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDXN1cHBvcnRlcnNLZXkBBQpuZXdDaGFpbklkCQClCAEIBQFpDG9yaWdpbkNhbGxlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUObGFzdENoYWluSWRLZXkFCm5ld0NoYWluSWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5leHRlbmRBbHRDaGFpbgYMYmxvY2tIYXNoSGV4DHJlZmVyZW5jZUhleAN2cmYHY2hhaW5JZBdlMmNUcmFuc2ZlcnNSb290SGFzaEhleBRsYXN0QzJFVHJhbnNmZXJJbmRleAQOY2hlY2tCbG9ja0hhc2gJARF2YWxpZGF0ZUJsb2NrSGFzaAEFDGJsb2NrSGFzaEhleAMJAAACBQ5jaGVja0Jsb2NrSGFzaAUOY2hlY2tCbG9ja0hhc2gECmNoZWNrRXBvY2gJARJlbnN1cmVDb3JyZWN0RXBvY2gBBQN2cmYDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQTY2hhaW5GaXJzdEJsb2NrTWV0YQkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEFB2NoYWluSWQECmNoZWNrQ2hhaW4JAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMIBQFpDG9yaWdpbkNhbGxlcgUHY2hhaW5JZAkA3AQBCAUTY2hhaW5GaXJzdEJsb2NrTWV0YQJfMwMJAAACBQpjaGVja0NoYWluBQpjaGVja0NoYWluBA0kdDAxOTcxNjE5NzcwCQEJY2hhaW5NZXRhAQUHY2hhaW5JZAQLY2hhaW5IZWlnaHQIBQ0kdDAxOTcxNjE5NzcwAl8xBA5jaGFpbkxhc3RCbG9jawgFDSR0MDE5NzE2MTk3NzACXzIEDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BQ5jaGFpbkxhc3RCbG9jawMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al82BRRsYXN0QzJFVHJhbnNmZXJJbmRleAYDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEECXByZXZFcG9jaAgJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgCXzIEE3VwZGF0ZU1haW5DaGFpbkRhdGEDCQBmAgkBEXN1cHBvcnRpbmdCYWxhbmNlAQUHY2hhaW5JZAkAaQIFFGNvbXB1dGVkVG90YWxCYWxhbmNlAAIEC2xhc3RDaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAEFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQEdZ2V0VXBkYXRlRmluYWxpemVkQmxvY2tBY3Rpb24DCAUBaQxvcmlnaW5DYWxsZXIFDGJsb2NrSGFzaEhleAUJcHJldkVwb2NoCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARRjaGFpbkZvcmtlZEhlaWdodEtleQEFC21haW5DaGFpbklkCAUTY2hhaW5GaXJzdEJsb2NrTWV0YQJfMQkAzAgCCQEMSW50ZWdlckVudHJ5AgUObWFpbkNoYWluSWRLZXkFB2NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIFF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5CQBkAgULbGFzdENoYWluSWQAAQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawUDbmlsBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQlwcmV2RXBvY2gFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAMJAAACBQ10aGlzRXBvY2hNZXRhBQ10aGlzRXBvY2hNZXRhBA5jaGVja0dlbmVyYXRvcgkBEWVuc3VyZU1pbmluZ0Vwb2NoAQgFAWkMb3JpZ2luQ2FsbGVyAwkAAAIFDmNoZWNrR2VuZXJhdG9yBQ5jaGVja0dlbmVyYXRvcgQddXBkYXRlTWFpbkNoYWluTGFzdE1pbmVkQmxvY2sDAwkAAAIFE3VwZGF0ZU1haW5DaGFpbkRhdGEFA25pbAkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkBDG1pbmVyQ2hhaW5JZAEIBQFpDG9yaWdpbkNhbGxlcgAABQdjaGFpbklkBwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIIBRNjaGFpbkZpcnN0QmxvY2tNZXRhAl8xBQNuaWwFA25pbAkAzggCCQDOCAIJAM4IAgkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQYFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFDHJlZmVyZW5jZUhleAUHY2hhaW5JZAUXZTJjVHJhbnNmZXJzUm9vdEhhc2hIZXgFFGxhc3RDMkVUcmFuc2ZlckluZGV4CQDMCAIJARBta0NoYWluTWV0YUVudHJ5AwUHY2hhaW5JZAUObmV3Q2hhaW5IZWlnaHQFDGJsb2NrSGFzaEhleAkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPbWluZXJDaGFpbklkS2V5AQgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAUDbmlsBRN1cGRhdGVNYWluQ2hhaW5EYXRhCQEMYWRkU3VwcG9ydGVyAgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBR11cGRhdGVNYWluQ2hhaW5MYXN0TWluZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQthcHBlbmRCbG9jawQMYmxvY2tIYXNoSGV4DHJlZmVyZW5jZUhleBdlMmNUcmFuc2ZlcnNSb290SGFzaEhleBRsYXN0QzJFVHJhbnNmZXJJbmRleAQLY2hlY2tDYWxsZXIDCQAAAgUOdGhpc0Vwb2NoTWluZXIIBQFpDG9yaWdpbkNhbGxlcgYEByRtYXRjaDAFDnRoaXNFcG9jaE1pbmVyAwkAAQIFByRtYXRjaDACB0FkZHJlc3MECmVwb2NoTWluZXIFByRtYXRjaDAJAAIBCQCsAgICOW5vdCBhbGxvd2VkIHRvIGZvcmdlIGJsb2NrcyBpbiB0aGlzIGVwb2NoLCBleHBlY3RlZCBmcm9tIAkApQgBBQplcG9jaE1pbmVyCQACAQJAbm90IGFsbG93ZWQgdG8gZm9yZ2UgYmxvY2tzIGluIHRoaXMgZXBvY2gsIGVwb2NoIG1pbmVyIGlzIGFic2VudAMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIEB2NoYWluSWQJAQt2YWx1ZU9yRWxzZQIJAQxtaW5lckNoYWluSWQBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBA0kdDAyMjExOTIyMTcwCQEJY2hhaW5NZXRhAQUHY2hhaW5JZAQLY2hhaW5IZWlnaHQIBQ0kdDAyMjExOTIyMTcwAl8xBAtsYXN0QmxvY2tJZAgFDSR0MDIyMTE5MjIxNzACXzIEDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BQtsYXN0QmxvY2tJZAMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al82BRRsYXN0QzJFVHJhbnNmZXJJbmRleAcDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoCQDMCAIJARBta0Jsb2NrTWV0YUVudHJ5BgUMYmxvY2tIYXNoSGV4BQ5uZXdDaGFpbkhlaWdodAULbGFzdEJsb2NrSWQFB2NoYWluSWQFF2UyY1RyYW5zZmVyc1Jvb3RIYXNoSGV4BRRsYXN0QzJFVHJhbnNmZXJJbmRleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQdjaGFpbklkBQ5uZXdDaGFpbkhlaWdodAUMYmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCQEFdmFsdWUBBQ50aGlzRXBvY2hNaW5lcgUDU0VQCQCkAwEFDHRoaXNFcG9jaFJlZgUDU0VQBQxibG9ja0hhc2hIZXgFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQRqb2luARByZXdhcmRBZGRyZXNzSGV4CgEdZW5zdXJlTm90T3ZlcnJpZGVPdGhlck1pbmVyUGsBDGVsQWRkcmVzc0hleAQHJG1hdGNoMAkAoQgBCQEKbWluZXJQa0tleQEFDGVsQWRkcmVzc0hleAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJwawUHJG1hdGNoMAMJAAACBQJwawgFAWkVb3JpZ2luQ2FsbGVyUHVibGljS2V5BQR1bml0CQACAQkArAICCQCsAgIJAKwCAgIRRUwgbWluZXIgYWRkcmVzcyAFDGVsQWRkcmVzc0hleAIYIGlzIGFscmVhZHkgbGlua2VkIHdpdGggCQDYBAEFAnBrBQR1bml0BAVwYXJ0cwkAtQkCBRByZXdhcmRBZGRyZXNzSGV4AgIweAQNcmV3YXJkQWRkcmVzcwkA3QQBCQCRAwIFBXBhcnRzCQBlAgkAkAMBBQVwYXJ0cwABAwkBASEBCQEPaXNDb250cmFjdFNldHVwAAkAAgECH1RoZSBjb250cmFjdCBoYXMgbm90IHlldCBzZXQgdXADCQBmAgULTUlOX0JBTEFOQ0UICQDvBwEIBQFpDG9yaWdpbkNhbGxlcgpnZW5lcmF0aW5nCQACAQkArAICCQCsAgIJAKwCAgIhSW5zdWZmaWNpZW50IGdlbmVyYXRpbmcgYmFsYW5jZTogCQCkAwEICQDvBwEIBQFpDG9yaWdpbkNhbGxlcgpnZW5lcmF0aW5nAgwuIFJlcXVpcmVkOiAJAKQDAQULTUlOX0JBTEFOQ0UDCQECIT0CCQDIAQEFDXJld2FyZEFkZHJlc3MAFAkAAgECJXJld2FyZEFkZHJlc3Mgc2hvdWxkIGJlIGFuIEwyIGFkZHJlc3MDCQBnAgkAkAMBBQlhbGxNaW5lcnMAMgkAAgECD3RvbyBtYW55IG1pbmVycwoBDmNoZWNrRXhpc3RlbmNlAgZleGlzdHMFbWluZXIDBQZleGlzdHMGCQAAAgUFbWluZXIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBA1hbHJlYWR5RXhpc3RzCgACJGwFCWFsbE1pbmVycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAHCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ5jaGVja0V4aXN0ZW5jZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgNTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyAwUNYWxyZWFkeUV4aXN0cwUDbmlsBAhuZXdNaW5lcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEFmxvd2VyY2FzZVJld2FyZEFkZHJlc3MJANwEAQUNcmV3YXJkQWRkcmVzcwQFY2hlY2sJAR1lbnN1cmVOb3RPdmVycmlkZU90aGVyTWluZXJQawEFFmxvd2VyY2FzZVJld2FyZEFkZHJlc3MDCQAAAgUFY2hlY2sFBWNoZWNrBAluZXdNaW5lcnMDCQAAAgkAkAMBBQlhbGxNaW5lcnMAAAUIbmV3TWluZXIJAKwCAgkArAICBQxhbGxNaW5lcnNTdHIFA1NFUAUIbmV3TWluZXIEGWRlbGV0ZVByZXZSZXdhcmRBZGRyZXNzUGsEByRtYXRjaDAJAKIIAQkBFW1pbmVyUmV3YXJkQWRkcmVzc0tleQEFCG5ld01pbmVyAwkAAQIFByRtYXRjaDACBlN0cmluZwQLcHJldkFkZHJlc3MFByRtYXRjaDADCQAAAgULcHJldkFkZHJlc3MJANwEAQUNcmV3YXJkQWRkcmVzcwUDbmlsCQDMCAIJAQtEZWxldGVFbnRyeQEJAQptaW5lclBrS2V5AQULcHJldkFkZHJlc3MFA25pbAUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUMYWxsTWluZXJzS2V5BQluZXdNaW5lcnMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFW1pbmVyUmV3YXJkQWRkcmVzc0tleQEFCG5ld01pbmVyCQCsAgICAjB4BRZsb3dlcmNhc2VSZXdhcmRBZGRyZXNzCQDMCAIJAQtCaW5hcnlFbnRyeQIJAQptaW5lclBrS2V5AQUWbG93ZXJjYXNlUmV3YXJkQWRkcmVzcwgFAWkVb3JpZ2luQ2FsbGVyUHVibGljS2V5BQNuaWwFGWRlbGV0ZVByZXZSZXdhcmRBZGRyZXNzUGsJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEFbGVhdmUABAxsZWF2aW5nTWluZXIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCgEQc2tpcExlYXZpbmdNaW5lcgIDYWNjBW1pbmVyAwkAAAIFBW1pbmVyBQxsZWF2aW5nTWluZXIFA2FjYwkAzQgCBQNhY2MFBW1pbmVyBA9yZW1haW5pbmdNaW5lcnMKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARBza2lwTGVhdmluZ01pbmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIEDXJld2FyZEFkZHJLZXkJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQxsZWF2aW5nTWluZXIEEXByZXZSZXdhcmRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhpcwUNcmV3YXJkQWRkcktleQIWbWluZXIgaGFzIG5ldmVyIGpvaW5lZAMJAAACBRFwcmV2UmV3YXJkQWRkcmVzcwURcHJldlJld2FyZEFkZHJlc3MDCQAAAgUOdGhpc0Vwb2NoTWluZXIIBQFpDG9yaWdpbkNhbGxlcgkAAgECHGRlc2lnbmF0ZWQgbWluZXIgY2FuJ3QgbGVhdmUJAMwIAgkBC1N0cmluZ0VudHJ5AgUMYWxsTWluZXJzS2V5CQC6CQIFD3JlbWFpbmluZ01pbmVycwUDU0VQBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEIdHJhbnNmZXIBEGRlc3RFbEFkZHJlc3NIZXgEDGNoZWNrQWRkcmVzcwMJAAACCQCxAgEFEGRlc3RFbEFkZHJlc3NIZXgFFEVUSF9BRERSRVNTX1NUUl9TSVpFCQDdBAEFEGRlc3RFbEFkZHJlc3NIZXgJAAIBCQCsAgIJAKwCAgkArAICAhRBZGRyZXNzIHNob3VsZCBoYXZlIAkApAMBBRRFVEhfQUREUkVTU19TVFJfU0laRQIRIGNoYXJhY3RlcnMsIGdvdCAJAKQDAQkAsQIBBRBkZXN0RWxBZGRyZXNzSGV4AwkAAAIFDGNoZWNrQWRkcmVzcwUMY2hlY2tBZGRyZXNzBAxjaGVja1BheW1lbnQDCQAAAgkAkAMBCAUBaQhwYXltZW50cwABBgkAAgEJAKwCAgIvRXhwZWN0ZWQgb25lIHBheW1lbnQgYXMgYSB0cmFuc2ZlciBhbW91bnQsIGdvdCAJAKQDAQkAkAMBCAUBaQhwYXltZW50cwMJAAACBQxjaGVja1BheW1lbnQFDGNoZWNrUGF5bWVudAQKdG9rZW5JZFN0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQUKdG9rZW5JZEtleQQHdG9rZW5JZAkA2QQBBQp0b2tlbklkU3RyBAF0CQCRAwIIBQFpCHBheW1lbnRzAAAEDGNoZWNrQXNzZXRJZAQHJG1hdGNoMAgFAXQHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAdhc3NldElkBQckbWF0Y2gwAwkAAAIFB2Fzc2V0SWQFB3Rva2VuSWQGCQACAQkArAICCQCsAgIJAKwCAgIJRXhwZWN0ZWQgBQp0b2tlbklkU3RyAhUgaW4gdGhlIHBheW1lbnQsIGdvdCAJANgEAQUHYXNzZXRJZAkAAgEJAKwCAgkArAICAglFeHBlY3RlZCAFCnRva2VuSWRTdHICGiBpbiB0aGUgcGF5bWVudCwgZ290IFdhdmVzAwkAAAIFDGNoZWNrQXNzZXRJZAUMY2hlY2tBc3NldElkBAlsYXN0SW5kZXgICQEJYmxvY2tNZXRhAQUSbWFpbkNoYWluTGFzdEJsb2NrAl82BAlxdWV1ZVNpemUJAGUCBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAUJbGFzdEluZGV4BA9jaGVja1F1ZXVlTGltaXQDCQBmAgCgAQUJcXVldWVTaXplCQEKYW1vdW50R3RFcQMFAXQAwIQ9BQlxdWV1ZVNpemUDCQBmAgDADAUJcXVldWVTaXplCQEKYW1vdW50R3RFcQMFAXQAgK3iBAUJcXVldWVTaXplAwkAZgIAgBkFCXF1ZXVlU2l6ZQkBCmFtb3VudEd0RXEDBQF0AIDC1y8FCXF1ZXVlU2l6ZQMJAGYCAIAyBQlxdWV1ZVNpemUJAQphbW91bnRHdEVxAwUBdACAlOvcAwUJcXVldWVTaXplCQACAQkArAICCQCsAgICI1RyYW5zZmVycyBkZW5pZWQgZm9yIHF1ZXVlIHNpemUgb2YgCQCkAwEFCXF1ZXVlU2l6ZQIoLiBXYWl0IHVudGlsIGN1cnJlbnQgdHJhbnNmZXJzIHByb2Nlc3NlZAMJAAACBQ9jaGVja1F1ZXVlTGltaXQFD2NoZWNrUXVldWVMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXbmF0aXZlVHJhbnNmZXJzQ291bnRLZXkJAGQCBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAABCQDMCAIJARVta05hdGl2ZVRyYW5zZmVyRW50cnkDBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAUQZGVzdEVsQWRkcmVzc0hleAgFAXQGYW1vdW50CQDMCAIJAQRCdXJuAgUHdG9rZW5JZAgFAXQGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEId2l0aGRyYXcEDGJsb2NrSGFzaEhleAttZXJrbGVQcm9vZhR0cmFuc2ZlckluZGV4SW5CbG9jawZhbW91bnQEEXdpdGhkcmF3QmxvY2tNZXRhCQEJYmxvY2tNZXRhAQUMYmxvY2tIYXNoSGV4BBN3aXRoZHJhd0Jsb2NrSGVpZ2h0CAURd2l0aGRyYXdCbG9ja01ldGECXzEEFGZpbmFsaXplZEJsb2NrSGVpZ2h0CAkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFEWZpbmFsaXplZEJsb2NrS2V5Al8xBBhtYWluQ2hhaW5MYXN0QmxvY2tIZWlnaHQICQEJYmxvY2tNZXRhAQUSbWFpbkNoYWluTGFzdEJsb2NrAl8xAwkAZgIFE3dpdGhkcmF3QmxvY2tIZWlnaHQFFGZpbmFsaXplZEJsb2NrSGVpZ2h0CQACAQkArAICCQCsAgIJAKwCAgIKRUwgYmxvY2sgIwkApAMBBRN3aXRoZHJhd0Jsb2NrSGVpZ2h0Ai0gaXMgbm90IGZpbmFsaXplZC4gVGhlIGN1cnJlbnQgZmluYWxpemVkIGlzICMJAKQDAQUUZmluYWxpemVkQmxvY2tIZWlnaHQDCQECIT0CCQCQAwEFC21lcmtsZVByb29mBRRXSVRIRFJBV19QUk9PRlNfU0laRQkAAgEJAKwCAgkArAICCQCsAgICCUV4cGVjdGVkIAkApAMBBRRXSVRIRFJBV19QUk9PRlNfU0laRQINIHByb29mcywgZ290IAkApAMBCQCQAwEFC21lcmtsZVByb29mAwkAZgIAAAUUdHJhbnNmZXJJbmRleEluQmxvY2sJAAIBCQCsAgICM1RyYW5zZmVyIGluZGV4IGluIGJsb2NrIHNob3VsZCBiZSBub25uZWdhdGl2ZSwgZ290IAkApAMBBRR0cmFuc2ZlckluZGV4SW5CbG9jawMJAGcCAAAFBmFtb3VudAkAAgEJAKwCAgIfQW1vdW50IHNob3VsZCBiZSBwb3NpdGl2ZSwgZ290IAkApAMBBQZhbW91bnQEFHdpdGhkcmF3QmxvY2tDaGFpbklkCAURd2l0aGRyYXdCbG9ja01ldGECXzQEC2lzTWFpbkNoYWluCQAAAgUUd2l0aGRyYXdCbG9ja0NoYWluSWQFC21haW5DaGFpbklkBBJyZWxhdGVzVG9NYWluQ2hhaW4EByRtYXRjaDAJAJ8IAQkBFGNoYWluRm9ya2VkSGVpZ2h0S2V5AQUUd2l0aGRyYXdCbG9ja0NoYWluSWQDCQABAgUHJG1hdGNoMAIDSW50BAxmb3JrZWRIZWlnaHQFByRtYXRjaDAJAGYCBQxmb3JrZWRIZWlnaHQFE3dpdGhkcmF3QmxvY2tIZWlnaHQJAAIBCQCsAgIJAKwCAgkArAICBQxibG9ja0hhc2hIZXgCHSBpcyBvbiBhbiBhbHRlcm5hdGl2ZSBjaGFpbiAjCQCkAwEFFHdpdGhkcmF3QmxvY2tDaGFpbklkAjggdGhhdCB3YXMgbm90IGFwcHJvdmVkIGJ5IG1ham9yaXR5LiBXYWl0IGZvciBzb21lIGJsb2NrcwMDBQtpc01haW5DaGFpbgYFEnJlbGF0ZXNUb01haW5DaGFpbgQJcmVjaXBpZW50CAUBaQxvcmlnaW5DYWxsZXIED3JlY2lwaWVudFBrSGFzaAkAyQECCQDKAQIIBQlyZWNpcGllbnQFYnl0ZXMAAgUUUFVCTElDX0tFWV9IQVNIX1NJWkUED3plcm9BbW91bnRCeXRlcwEsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEC2Ftb3VudEJ5dGVzCQCaAwEFBmFtb3VudAQLZWxFdmVudERhdGEJAMsBAgkAywECBQ9yZWNpcGllbnRQa0hhc2gJAMkBAgUPemVyb0Ftb3VudEJ5dGVzCQBlAgkAyAEBBQ96ZXJvQW1vdW50Qnl0ZXMJAMgBAQULYW1vdW50Qnl0ZXMFC2Ftb3VudEJ5dGVzBBFlbEV2ZW50RGF0YURpZ2VzdAkA8BUBBQtlbEV2ZW50RGF0YQQSY2FsY3VsYXRlZFJvb3RIYXNoCQC9BQMFC21lcmtsZVByb29mBRFlbEV2ZW50RGF0YURpZ2VzdAUUdHJhbnNmZXJJbmRleEluQmxvY2sEEGV4cGVjdGVkUm9vdEhhc2gIBRF3aXRoZHJhd0Jsb2NrTWV0YQJfNQMJAAACBRJjYWxjdWxhdGVkUm9vdEhhc2gFEGV4cGVjdGVkUm9vdEhhc2gEB3Rva2VuSWQJANkEAQkBEUBleHRyTmF0aXZlKDEwNTgpAQUKdG9rZW5JZEtleQQMdHJhbnNmZXJzS2V5CQEUYmxvY2tFMkNUcmFuc2ZlcnNLZXkBBQxibG9ja0hhc2hIZXgJAMwIAgkBB1JlaXNzdWUDBQd0b2tlbklkBQZhbW91bnQGCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCXJlY2lwaWVudAUGYW1vdW50BQd0b2tlbklkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDHRyYW5zZmVyc0tleQkBCXNldE9yRmFpbAIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUMdHJhbnNmZXJzS2V5AgAFFHRyYW5zZmVySW5kZXhJbkJsb2NrBQNuaWwJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhRFeHBlY3RlZCByb290IGhhc2g6IAkA3AQBBRBleHBlY3RlZFJvb3RIYXNoAgcsIGdvdDogCQDcBAEFEmNhbGN1bGF0ZWRSb290SGFzaAIVLiBFdmVudCBkYXRhIGRpZ2VzdDogCQDaBAEFEWVsRXZlbnREYXRhRGlnZXN0Ah8uIENoZWNrIHlvdXIgd2l0aGRyYXcgYXJndW1lbnRzCQACAQkArAICCQCsAgICCUV4cGVjdGVkIAUMYmxvY2tIYXNoSGV4Ai8gdG8gYmUgZWl0aGVyIG9uIHRoZSBtYWluIGNoYWluIG9yIHJlbGF0ZSB0byBpdAFpAQVzZXR1cAQTZ2VuZXNpc0Jsb2NrSGFzaEhleBFtaW5lclJld2FyZEluR3dlaQpkYW9BZGRyZXNzCWRhb1Jld2FyZAMJAQ9pc0NvbnRyYWN0U2V0dXAACQACAQIkVGhlIGNvbnRyYWN0IGhhcyBiZWVuIGFscmVhZHkgc2V0IHVwAwkAZgIAAAURbWluZXJSZXdhcmRJbkd3ZWkJAAIBAiRUaGUgbWluZXIgcmV3YXJkIG11c3QgYmUgbm9ubmVnYXRpdmUEEGdlbmVzaXNCbG9ja0hhc2gJAN0EAQUTZ2VuZXNpc0Jsb2NrSGFzaEhleAQZY2hlY2tHZW5lc2lzQmxvY2tIYXNoU2l6ZQMJAAACCQDIAQEFEGdlbmVzaXNCbG9ja0hhc2gFD0JMT0NLX0hBU0hfU0laRQYJAAIBAhhXcm9uZyBnZW5lc2lzIGJsb2NrIGhhc2gDCQAAAgUZY2hlY2tHZW5lc2lzQmxvY2tIYXNoU2l6ZQUZY2hlY2tHZW5lc2lzQmxvY2tIYXNoU2l6ZQQHZW1wdHlQawEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE2dlbmVzaXNNaW5lckFkZHJlc3MJAKcIAQUHZW1wdHlQawQXZ2VuZXNpc0V0aFJld2FyZEFkZHJlc3MBFAAAAAAAAAAAAAAAAAAAAAAAAAAABBlnZW5lc2lzQmxvY2tSZWZlcmVuY2VIYXNoAkAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBAVpc3N1ZQkAwggFAgVVTklUMAIMTmF0aXZlIHRva2VuAAAACAYEB3Rva2VuSWQJALgIAQUFaXNzdWUEEGdlbmVzaXNCbG9ja01ldGEJARBta0Jsb2NrTWV0YUVudHJ5BgUTZ2VuZXNpc0Jsb2NrSGFzaEhleAAABRlnZW5lc2lzQmxvY2tSZWZlcmVuY2VIYXNoAAAJANwEAQEAAP///////////wEECmRhb0VudHJpZXMDCQAAAgUKZGFvQWRkcmVzcwIABQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgUNZGFvQWRkcmVzc0tleQkApQgBCQEHQWRkcmVzcwEJANkEAQUKZGFvQWRkcmVzcwkAzAgCCQEMSW50ZWdlckVudHJ5AgUMZGFvUmV3YXJkS2V5AwkAZgIFCWRhb1Jld2FyZAAABQlkYW9SZXdhcmQJAAIBAhlpbnZhbGlkIERBTyByZXdhcmQgYW1vdW50BQNuaWwJAM4IAgkAzAgCBRBnZW5lc2lzQmxvY2tNZXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEAAAUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCCQEQbWtDaGFpbk1ldGFFbnRyeQMAAAAABRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5taW5lclJld2FyZEtleQURbWluZXJSZXdhcmRJbkd3ZWkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKUIAQUTZ2VuZXNpc01pbmVyQWRkcmVzcwIDLDAsBRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIFEWZpbmFsaXplZEJsb2NrS2V5BRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIFBWlzc3VlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCnRva2VuSWRLZXkJANgEAQUHdG9rZW5JZAkAzAgCCQELU3RyaW5nRW50cnkCBRJlbEJyaWRnZUFkZHJlc3NLZXkCKjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNmE3ZQUDbmlsBQpkYW9FbnRyaWVzCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAOKF2ww=", "height": 3340644, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 36fQejUN2YzRW7ooET6swSK1pmxdjwxwfafH8YBAXWyc Next: none Diff:
Old | New | Differences | |
---|---|---|---|
23 | 23 | ||
24 | 24 | let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" | |
25 | 25 | ||
26 | + | let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "") | |
27 | + | ||
26 | 28 | let allMinersKey = "allMiners" | |
27 | 29 | ||
28 | 30 | let mainChainIdKey = "mainChainId" | |
42 | 44 | let elBridgeAddressKey = "elBridgeAddress" | |
43 | 45 | ||
44 | 46 | let nativeTransfersCountKey = "nativeTransfersCount" | |
47 | + | ||
48 | + | let daoAddressKey = "daoAddress" | |
49 | + | ||
50 | + | let daoRewardKey = "daoReward" | |
45 | 51 | ||
46 | 52 | func pad (i) = { | |
47 | 53 | let s = toString(i) | |
140 | 146 | ||
141 | 147 | let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0) | |
142 | 148 | ||
143 | - | let $ | |
149 | + | let $t052495315 = chainMeta(mainChainId) | |
144 | 150 | ||
145 | - | let mainChainHeight = $ | |
151 | + | let mainChainHeight = $t052495315._1 | |
146 | 152 | ||
147 | - | let mainChainLastBlock = $ | |
153 | + | let mainChainLastBlock = $t052495315._2 | |
148 | 154 | ||
149 | 155 | func epochMeta (epoch) = match getString(epochMetaKey(epoch)) { | |
150 | 156 | case s: String => | |
155 | 161 | } | |
156 | 162 | ||
157 | 163 | ||
158 | - | let $ | |
164 | + | let $t055465670 = match epochMeta(height) { | |
159 | 165 | case m: (Address, Int, String) => | |
160 | 166 | m | |
161 | 167 | case _ => | |
162 | 168 | $Tuple2(unit, 0) | |
163 | 169 | } | |
164 | 170 | ||
165 | - | let thisEpochMiner = $ | |
171 | + | let thisEpochMiner = $t055465670._1 | |
166 | 172 | ||
167 | - | let thisEpochRef = $ | |
173 | + | let thisEpochRef = $t055465670._2 | |
168 | 174 | ||
169 | 175 | let allMinersStr = valueOrElse(getString(allMinersKey), "") | |
170 | 176 | ||
227 | 233 | } | |
228 | 234 | ||
229 | 235 | ||
230 | - | let $ | |
236 | + | let $t077108645 = { | |
231 | 237 | let hitSource = match lastBlock.vrf { | |
232 | 238 | case vrf: ByteVector => | |
233 | 239 | vrf | |
235 | 241 | lastBlock.generationSignature | |
236 | 242 | } | |
237 | 243 | func processMiner (prev,miner) = { | |
238 | - | let $ | |
239 | - | let prevMiner = $ | |
240 | - | let prevTotalBalance = $ | |
241 | - | let prevDelay = $ | |
242 | - | let prevMiners = $ | |
244 | + | let $t079778040 = prev | |
245 | + | let prevMiner = $t079778040._1 | |
246 | + | let prevTotalBalance = $t079778040._2 | |
247 | + | let prevDelay = $t079778040._3 | |
248 | + | let prevMiners = $t079778040._4 | |
243 | 249 | let minerAddress = addressFromStringValue(miner) | |
244 | 250 | let wavesGenBalance = wavesBalance(minerAddress).generating | |
245 | 251 | let minerBalance = generatingBalance(minerAddress) | |
269 | 275 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50) | |
270 | 276 | } | |
271 | 277 | ||
272 | - | let computedGenerator = $ | |
278 | + | let computedGenerator = $t077108645._1 | |
273 | 279 | ||
274 | - | let computedTotalBalance = $ | |
280 | + | let computedTotalBalance = $t077108645._2 | |
275 | 281 | ||
276 | - | let $ | |
282 | + | let $t086478713 = blockMeta(mainChainLastBlock) | |
277 | 283 | ||
278 | - | let mclbIgnored1 = $ | |
284 | + | let mclbIgnored1 = $t086478713._1 | |
279 | 285 | ||
280 | - | let mainChainEpoch = $ | |
286 | + | let mainChainEpoch = $t086478713._2 | |
281 | 287 | ||
282 | - | func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = { | |
283 | - | let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "") | |
288 | + | func calculateFinalizedBlockHashAndEpoch (curMiner,curPrevEpoch,curLastBlockHash) = { | |
284 | 289 | let halfBalance = (computedTotalBalance / 2) | |
285 | 290 | func step (prev,next) = { | |
286 | - | let $ | |
287 | - | let thisEpoch = $ | |
288 | - | let | |
289 | - | let totalBalance = $ | |
290 | - | let prevMiners = $ | |
291 | - | match | |
291 | + | let $t089519024 = prev | |
292 | + | let thisEpoch = $t089519024._1 | |
293 | + | let maybeFinalizedBlockHash = $t089519024._2 | |
294 | + | let totalBalance = $t089519024._3 | |
295 | + | let prevMiners = $t089519024._4 | |
296 | + | match maybeFinalizedBlockHash { | |
292 | 297 | case _: Unit => | |
293 | - | let $ | |
298 | + | let $t090919257 = if ((thisEpoch == height)) | |
294 | 299 | then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash) | |
295 | 300 | else value(epochMeta(thisEpoch)) | |
296 | - | let miner = $ | |
297 | - | let prevEpoch = $ | |
298 | - | let lastBlockHash = $ | |
301 | + | let miner = $t090919257._1 | |
302 | + | let prevEpoch = $t090919257._2 | |
303 | + | let lastBlockHash = $t090919257._3 | |
299 | 304 | if (if ((prevEpoch == 0)) | |
300 | 305 | then true | |
301 | 306 | else ((height - thisEpoch) >= 100)) | |
302 | 307 | then $Tuple4(thisEpoch, lastBlockHash, totalBalance, allMiners) | |
303 | 308 | else { | |
304 | - | let $ | |
309 | + | let $t094119613 = if (containsElement(prevMiners, miner)) | |
305 | 310 | then $Tuple2(totalBalance, prevMiners) | |
306 | 311 | else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners) | |
307 | - | let newTotalBalance = $ | |
308 | - | let newMiners = $ | |
312 | + | let newTotalBalance = $t094119613._1 | |
313 | + | let newMiners = $t094119613._2 | |
309 | 314 | if ((newTotalBalance > halfBalance)) | |
310 | 315 | then $Tuple4(thisEpoch, lastBlockHash, newTotalBalance, allMiners) | |
311 | 316 | else $Tuple4(prevEpoch, unit, newTotalBalance, newMiners) | |
315 | 320 | } | |
316 | 321 | } | |
317 | 322 | ||
318 | - | let $ | |
323 | + | let $t098469943 = { | |
319 | 324 | let $l = offsets_100 | |
320 | 325 | let $s = size($l) | |
321 | 326 | let $acc0 = $Tuple4(height, unit, 0, nil) | |
329 | 334 | ||
330 | 335 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
331 | 336 | } | |
332 | - | let | |
333 | - | let finalizedBlockHashOpt = $ | |
334 | - | match finalizedBlockHashOpt { | |
337 | + | let finalizedEpoch = $t098469943._1 | |
338 | + | let finalizedBlockHashOpt = $t098469943._2 | |
339 | + | $Tuple2( match finalizedBlockHashOpt { | |
335 | 340 | case finalizedBlockHash: String => | |
336 | 341 | finalizedBlockHash | |
337 | 342 | case _ => | |
338 | - | value(epochMeta( | |
339 | - | } | |
343 | + | value(epochMeta(finalizedEpoch))._3 | |
344 | + | }, finalizedEpoch) | |
340 | 345 | } | |
341 | 346 | ||
342 | 347 | ||
343 | 348 | func supportingBalance (chainId) = { | |
344 | 349 | func addBalance (acc,generatorStr) = { | |
345 | - | let $ | |
346 | - | let totalBalance = $ | |
347 | - | let generators = $ | |
350 | + | let $t01022610262 = acc | |
351 | + | let totalBalance = $t01022610262._1 | |
352 | + | let generators = $t01022610262._2 | |
348 | 353 | let generator = addressFromStringValue(generatorStr) | |
349 | 354 | if (containsElement(generators, generator)) | |
350 | 355 | then acc | |
355 | 360 | } | |
356 | 361 | ||
357 | 362 | let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP) | |
358 | - | let | |
363 | + | let res = { | |
359 | 364 | let $l = allGenerators | |
360 | 365 | let $s = size($l) | |
361 | 366 | let $acc0 = $Tuple2(0, nil) | |
369 | 374 | ||
370 | 375 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
371 | 376 | } | |
372 | - | let balance = $t01046010525._1 | |
373 | - | let _g = $t01046010525._2 | |
374 | - | balance | |
377 | + | res._1 | |
375 | 378 | } | |
376 | 379 | ||
377 | 380 | ||
475 | 478 | ||
476 | 479 | ||
477 | 480 | func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = { | |
478 | - | let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1 | |
479 | - | let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex) | |
480 | - | if (if ((newFinalizedBlockHash == newBlockHashHex)) | |
481 | + | let curFinalizedBlockMeta = blockMeta(getStringValue(finalizedBlockKey)) | |
482 | + | let $t01427314393 = calculateFinalizedBlockHashAndEpoch(caller, prevEpoch, newBlockHashHex) | |
483 | + | let newFinalizedBlockHash = $t01427314393._1 | |
484 | + | let newFinalizedEpoch = $t01427314393._2 | |
485 | + | let rewardActions = match getString(daoAddressKey) { | |
486 | + | case addr: String => | |
487 | + | if ((newFinalizedEpoch == curFinalizedBlockMeta._2)) | |
488 | + | then nil | |
489 | + | else { | |
490 | + | func countNonEmptyEpochs (acc,next) = if ((acc._1 == curFinalizedBlockMeta._2)) | |
491 | + | then acc | |
492 | + | else match epochMeta(acc._1) { | |
493 | + | case m: (Address, Int, String) => | |
494 | + | $Tuple2(m._2, (acc._2 + 1)) | |
495 | + | case _ => | |
496 | + | acc | |
497 | + | } | |
498 | + | ||
499 | + | let startFromEpoch = if ((newFinalizedEpoch == height)) | |
500 | + | then prevEpoch | |
501 | + | else valueOrErrorMessage(epochMeta(newFinalizedEpoch), "no prev epoch for start")._2 | |
502 | + | let daoRewards = { | |
503 | + | let $l = offsets_100 | |
504 | + | let $s = size($l) | |
505 | + | let $acc0 = $Tuple2(startFromEpoch, 1) | |
506 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
507 | + | then $a | |
508 | + | else countNonEmptyEpochs($a, $l[$i]) | |
509 | + | ||
510 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
511 | + | then $a | |
512 | + | else throw("List size exceeds 100") | |
513 | + | ||
514 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
515 | + | } | |
516 | + | let reissueAmount = (daoRewards._2 * getIntegerValue(daoRewardKey)) | |
517 | + | let tokenId = fromBase58String(getStringValue(tokenIdKey)) | |
518 | + | [Reissue(tokenId, reissueAmount, true), ScriptTransfer(Address(fromBase58String(addr)), reissueAmount, tokenId)] | |
519 | + | } | |
520 | + | case _ => | |
521 | + | nil | |
522 | + | } | |
523 | + | (rewardActions ++ (if (if ((newFinalizedBlockHash == newBlockHashHex)) | |
481 | 524 | then true | |
482 | - | else (blockMeta(newFinalizedBlockHash)._1 > | |
525 | + | else (blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockMeta._1)) | |
483 | 526 | then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)] | |
484 | - | else nil | |
527 | + | else nil)) | |
485 | 528 | } | |
486 | 529 | ||
487 | 530 | ||
542 | 585 | let checkEpoch = ensureCorrectEpoch(vrf) | |
543 | 586 | if ((checkEpoch == checkEpoch)) | |
544 | 587 | then { | |
545 | - | let $ | |
546 | - | let refChainHeight = $ | |
547 | - | let refEpoch = $ | |
548 | - | let refIgnored1 = $ | |
549 | - | let refIgnored2 = $ | |
550 | - | let refIgnored3 = $ | |
551 | - | let refTransferIndex = $ | |
588 | + | let $t01729017403 = blockMeta(referenceHex) | |
589 | + | let refChainHeight = $t01729017403._1 | |
590 | + | let refEpoch = $t01729017403._2 | |
591 | + | let refIgnored1 = $t01729017403._3 | |
592 | + | let refIgnored2 = $t01729017403._4 | |
593 | + | let refIgnored3 = $t01729017403._5 | |
594 | + | let refTransferIndex = $t01729017403._6 | |
552 | 595 | let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2 | |
553 | 596 | let epochRef = if ((refEpoch >= finalizedEpoch)) | |
554 | 597 | then refEpoch | |
595 | 638 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3)) | |
596 | 639 | if ((checkChain == checkChain)) | |
597 | 640 | then { | |
598 | - | let $ | |
599 | - | let chainHeight = $ | |
600 | - | let chainLastBlock = $ | |
641 | + | let $t01971619770 = chainMeta(chainId) | |
642 | + | let chainHeight = $t01971619770._1 | |
643 | + | let chainLastBlock = $t01971619770._2 | |
601 | 644 | let checkReference = isReferenceCorrect(referenceHex, chainLastBlock) | |
602 | 645 | if ((checkReference == checkReference)) | |
603 | 646 | then { | |
661 | 704 | if ((checkCaller == checkCaller)) | |
662 | 705 | then { | |
663 | 706 | let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId) | |
664 | - | let $ | |
665 | - | let chainHeight = $ | |
666 | - | let lastBlockId = $ | |
707 | + | let $t02211922170 = chainMeta(chainId) | |
708 | + | let chainHeight = $t02211922170._1 | |
709 | + | let lastBlockId = $t02211922170._2 | |
667 | 710 | let checkReference = isReferenceCorrect(referenceHex, lastBlockId) | |
668 | 711 | if ((checkReference == checkReference)) | |
669 | 712 | then { | |
884 | 927 | ||
885 | 928 | ||
886 | 929 | @Callable(i) | |
887 | - | func setup (genesisBlockHashHex,minerRewardInGwei) = if (isContractSetup()) | |
930 | + | func setup (genesisBlockHashHex,minerRewardInGwei,daoAddress,daoReward) = if (isContractSetup()) | |
888 | 931 | then throw("The contract has been already set up") | |
889 | 932 | else if ((0 > minerRewardInGwei)) | |
890 | 933 | then throw("The miner reward must be nonnegative") | |
902 | 945 | let issue = Issue("UNIT0", "Native token", 0, 8, true) | |
903 | 946 | let tokenId = calculateAssetId(issue) | |
904 | 947 | let genesisBlockMeta = mkBlockMetaEntry(genesisBlockHashHex, 0, genesisBlockReferenceHash, 0, toBase16String(base58''), -1) | |
905 | - | [genesisBlockMeta, StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, "0x0000000000000000000000000000000000006a7e")] | |
948 | + | let daoEntries = if ((daoAddress == "")) | |
949 | + | then nil | |
950 | + | else [StringEntry(daoAddressKey, toString(Address(fromBase58String(daoAddress)))), IntegerEntry(daoRewardKey, if ((daoReward > 0)) | |
951 | + | then daoReward | |
952 | + | else throw("invalid DAO reward amount"))] | |
953 | + | ([genesisBlockMeta, StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, "0x0000000000000000000000000000000000006a7e")] ++ daoEntries) | |
906 | 954 | } | |
907 | 955 | else throw("Strict value is not equal to itself.") | |
908 | 956 | } |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 8 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let INT_MAX = 9223372036854775807 | |
5 | 5 | ||
6 | 6 | let WAVES = 100000000 | |
7 | 7 | ||
8 | 8 | let MIN_BALANCE = (20000 * WAVES) | |
9 | 9 | ||
10 | 10 | let SEP = "," | |
11 | 11 | ||
12 | 12 | let BLOCK_HASH_SIZE = 32 | |
13 | 13 | ||
14 | 14 | let PUBLIC_KEY_HASH_SIZE = 20 | |
15 | 15 | ||
16 | 16 | let ROOT_HASH_SIZE = 32 | |
17 | 17 | ||
18 | 18 | let WITHDRAW_PROOFS_SIZE = 10 | |
19 | 19 | ||
20 | 20 | let ETH_ADDRESS_STR_SIZE = 40 | |
21 | 21 | ||
22 | 22 | let MAX_CL_TO_EL_TRANSFERS = 16 | |
23 | 23 | ||
24 | 24 | let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" | |
25 | 25 | ||
26 | + | let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "") | |
27 | + | ||
26 | 28 | let allMinersKey = "allMiners" | |
27 | 29 | ||
28 | 30 | let mainChainIdKey = "mainChainId" | |
29 | 31 | ||
30 | 32 | let lastChainIdKey = "lastChainId" | |
31 | 33 | ||
32 | 34 | let firstValidAltChainIdKey = "firstValidAltChainId" | |
33 | 35 | ||
34 | 36 | let minerRewardKey = "minerReward" | |
35 | 37 | ||
36 | 38 | let blockMetaK = "block_0x" | |
37 | 39 | ||
38 | 40 | let finalizedBlockKey = "finalizedBlock" | |
39 | 41 | ||
40 | 42 | let tokenIdKey = "tokenId" | |
41 | 43 | ||
42 | 44 | let elBridgeAddressKey = "elBridgeAddress" | |
43 | 45 | ||
44 | 46 | let nativeTransfersCountKey = "nativeTransfersCount" | |
47 | + | ||
48 | + | let daoAddressKey = "daoAddress" | |
49 | + | ||
50 | + | let daoRewardKey = "daoReward" | |
45 | 51 | ||
46 | 52 | func pad (i) = { | |
47 | 53 | let s = toString(i) | |
48 | 54 | match size(s) { | |
49 | 55 | case _ => | |
50 | 56 | if ((1 == $match0)) | |
51 | 57 | then ("0000000" + s) | |
52 | 58 | else if ((2 == $match0)) | |
53 | 59 | then ("000000" + s) | |
54 | 60 | else if ((3 == $match0)) | |
55 | 61 | then ("00000" + s) | |
56 | 62 | else if ((4 == $match0)) | |
57 | 63 | then ("0000" + s) | |
58 | 64 | else if ((5 == $match0)) | |
59 | 65 | then ("000" + s) | |
60 | 66 | else if ((6 == $match0)) | |
61 | 67 | then ("00" + s) | |
62 | 68 | else if ((7 == $match0)) | |
63 | 69 | then ("0" + s) | |
64 | 70 | else s | |
65 | 71 | } | |
66 | 72 | } | |
67 | 73 | ||
68 | 74 | ||
69 | 75 | func blockE2CTransfersKey (blockHashHex) = ("elToClTransfers_0x" + blockHashHex) | |
70 | 76 | ||
71 | 77 | ||
72 | 78 | func epochMetaKey (epoch) = ("epoch_" + pad(epoch)) | |
73 | 79 | ||
74 | 80 | ||
75 | 81 | func chainFirstBlockIdKey (chainId) = (("chain" + toString(chainId)) + "FirstBlock") | |
76 | 82 | ||
77 | 83 | ||
78 | 84 | func chainMetaKey (chainId) = ("chain_" + pad(chainId)) | |
79 | 85 | ||
80 | 86 | ||
81 | 87 | func chainLastHeightKey (chainId,miner) = ((("chain_" + pad(chainId)) + "_") + toString(miner)) | |
82 | 88 | ||
83 | 89 | ||
84 | 90 | func chainForkedHeightKey (chainId) = (("chain_" + pad(chainId)) + "ForkedHeight") | |
85 | 91 | ||
86 | 92 | ||
87 | 93 | func supportersKey (chainId) = (("chain" + toString(chainId)) + "Supporters") | |
88 | 94 | ||
89 | 95 | ||
90 | 96 | func minerRewardAddressKey (minerAddr) = (("miner_" + minerAddr) + "_RewardAddress") | |
91 | 97 | ||
92 | 98 | ||
93 | 99 | func minerPkKey (rewardAddress) = (("miner_0x" + rewardAddress) + "_PK") | |
94 | 100 | ||
95 | 101 | ||
96 | 102 | func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId") | |
97 | 103 | ||
98 | 104 | ||
99 | 105 | let nativeTransfersCount = valueOrElse(getInteger(this, nativeTransfersCountKey), 0) | |
100 | 106 | ||
101 | 107 | func nativeTransferKey (index) = ("nativeTransfer_" + toString(index)) | |
102 | 108 | ||
103 | 109 | ||
104 | 110 | func mkNativeTransferEntry (index,destElAddressHex,amount) = StringEntry(nativeTransferKey(index), ((("0x" + destElAddressHex) + SEP) + toString(amount))) | |
105 | 111 | ||
106 | 112 | ||
107 | 113 | func ensureCorrectTransfers (refTransferIndex,transferIndex,expectReward) = { | |
108 | 114 | let maxTransfers = if (expectReward) | |
109 | 115 | then (MAX_CL_TO_EL_TRANSFERS - 1) | |
110 | 116 | else MAX_CL_TO_EL_TRANSFERS | |
111 | 117 | let actualTransfers = (transferIndex - refTransferIndex) | |
112 | 118 | let checkNumber = if ((actualTransfers > maxTransfers)) | |
113 | 119 | then throw(((("Allowed only " + toString(maxTransfers)) + " transfers, got ") + toString(actualTransfers))) | |
114 | 120 | else true | |
115 | 121 | if ((checkNumber == checkNumber)) | |
116 | 122 | then if ((transferIndex >= nativeTransfersCount)) | |
117 | 123 | then throw(((("Attempt to transfer #" + toString(transferIndex)) + ". Available transfers: ") + toString(nativeTransfersCount))) | |
118 | 124 | else true | |
119 | 125 | else throw("Strict value is not equal to itself.") | |
120 | 126 | } | |
121 | 127 | ||
122 | 128 | ||
123 | 129 | func amountGtEq (t,gtEq,queueSize) = if ((t.amount >= gtEq)) | |
124 | 130 | then true | |
125 | 131 | else throw((((((("Transferring amount " + toString(t.amount)) + " should be >= ") + toString(gtEq)) + " for queue size of ") + toString(queueSize)) + ". Transfer more or wait")) | |
126 | 132 | ||
127 | 133 | ||
128 | 134 | func generatingBalance (address) = wavesBalance(address).generating | |
129 | 135 | ||
130 | 136 | ||
131 | 137 | func chainMeta (chainId) = { | |
132 | 138 | let s = getStringValue(chainMetaKey(chainId)) | |
133 | 139 | let items = split(s, SEP) | |
134 | 140 | $Tuple2(parseIntValue(items[0]), items[1]) | |
135 | 141 | } | |
136 | 142 | ||
137 | 143 | ||
138 | 144 | func mkChainMetaEntry (chainId,newChainHeight,blockHashHex) = StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)) | |
139 | 145 | ||
140 | 146 | ||
141 | 147 | let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0) | |
142 | 148 | ||
143 | - | let $ | |
149 | + | let $t052495315 = chainMeta(mainChainId) | |
144 | 150 | ||
145 | - | let mainChainHeight = $ | |
151 | + | let mainChainHeight = $t052495315._1 | |
146 | 152 | ||
147 | - | let mainChainLastBlock = $ | |
153 | + | let mainChainLastBlock = $t052495315._2 | |
148 | 154 | ||
149 | 155 | func epochMeta (epoch) = match getString(epochMetaKey(epoch)) { | |
150 | 156 | case s: String => | |
151 | 157 | let fragments = split(s, SEP) | |
152 | 158 | $Tuple3(addressFromStringValue(fragments[0]), parseIntValue(fragments[1]), fragments[2]) | |
153 | 159 | case _ => | |
154 | 160 | unit | |
155 | 161 | } | |
156 | 162 | ||
157 | 163 | ||
158 | - | let $ | |
164 | + | let $t055465670 = match epochMeta(height) { | |
159 | 165 | case m: (Address, Int, String) => | |
160 | 166 | m | |
161 | 167 | case _ => | |
162 | 168 | $Tuple2(unit, 0) | |
163 | 169 | } | |
164 | 170 | ||
165 | - | let thisEpochMiner = $ | |
171 | + | let thisEpochMiner = $t055465670._1 | |
166 | 172 | ||
167 | - | let thisEpochRef = $ | |
173 | + | let thisEpochRef = $t055465670._2 | |
168 | 174 | ||
169 | 175 | let allMinersStr = valueOrElse(getString(allMinersKey), "") | |
170 | 176 | ||
171 | 177 | let allMiners = match allMinersStr { | |
172 | 178 | case _ => | |
173 | 179 | if (("" == $match0)) | |
174 | 180 | then nil | |
175 | 181 | else if ($isInstanceOf($match0, "String")) | |
176 | 182 | then { | |
177 | 183 | let raw = $match0 | |
178 | 184 | split_4C(raw, SEP) | |
179 | 185 | } | |
180 | 186 | else throw("Match error") | |
181 | 187 | } | |
182 | 188 | ||
183 | 189 | func blockMeta (blockId) = { | |
184 | 190 | let meta = getBinaryValue((blockMetaK + blockId)) | |
185 | 191 | let metaSize = size(meta) | |
186 | 192 | let blockHeight = toInt(meta) | |
187 | 193 | let blockEpoch = toInt(meta, 8) | |
188 | 194 | let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE) | |
189 | 195 | let chainId = toInt(meta, (16 + BLOCK_HASH_SIZE)) | |
190 | 196 | let baseOffset = (24 + BLOCK_HASH_SIZE) | |
191 | 197 | let remainingBytes = (metaSize - baseOffset) | |
192 | 198 | let e2cTransfersRootHash = if ((remainingBytes >= ROOT_HASH_SIZE)) | |
193 | 199 | then take(drop(meta, baseOffset), ROOT_HASH_SIZE) | |
194 | 200 | else base58'' | |
195 | 201 | let lastC2ETransferIndex = if (if ((remainingBytes == 8)) | |
196 | 202 | then true | |
197 | 203 | else (remainingBytes > ROOT_HASH_SIZE)) | |
198 | 204 | then toInt(meta, (baseOffset + size(e2cTransfersRootHash))) | |
199 | 205 | else -1 | |
200 | 206 | $Tuple6(blockHeight, blockEpoch, blockParent, chainId, e2cTransfersRootHash, lastC2ETransferIndex) | |
201 | 207 | } | |
202 | 208 | ||
203 | 209 | ||
204 | 210 | func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,chainId,e2cTransfersRootHashHex,lastC2ETransferIndex) = { | |
205 | 211 | let e2cTransfersRootHashBytes = fromBase16String(e2cTransfersRootHashHex) | |
206 | 212 | let rootHashBytesSize = size(e2cTransfersRootHashBytes) | |
207 | 213 | let checkRootHash = if (if ((rootHashBytesSize == 0)) | |
208 | 214 | then true | |
209 | 215 | else (rootHashBytesSize == ROOT_HASH_SIZE)) | |
210 | 216 | then true | |
211 | 217 | else throw(((("Transfers root hash should have 0 or " + toString(ROOT_HASH_SIZE)) + " bytes, got ") + toString(rootHashBytesSize))) | |
212 | 218 | if ((checkRootHash == checkRootHash)) | |
213 | 219 | then { | |
214 | 220 | let blockMetaBytes = (((((toBytes(blockHeight) + toBytes(height)) + fromBase16String(blockParentHex)) + toBytes(chainId)) + e2cTransfersRootHashBytes) + toBytes(lastC2ETransferIndex)) | |
215 | 221 | BinaryEntry((blockMetaK + blockHashHex), blockMetaBytes) | |
216 | 222 | } | |
217 | 223 | else throw("Strict value is not equal to itself.") | |
218 | 224 | } | |
219 | 225 | ||
220 | 226 | ||
221 | 227 | func lastHeightBy (miner,chainId) = match getInteger(chainLastHeightKey(chainId, miner)) { | |
222 | 228 | case h: Int => | |
223 | 229 | h | |
224 | 230 | case _ => | |
225 | 231 | let blockHash = getStringValue(((("chain" + toString(chainId)) + "LastMinedBy") + toString(miner))) | |
226 | 232 | blockMeta(blockHash)._1 | |
227 | 233 | } | |
228 | 234 | ||
229 | 235 | ||
230 | - | let $ | |
236 | + | let $t077108645 = { | |
231 | 237 | let hitSource = match lastBlock.vrf { | |
232 | 238 | case vrf: ByteVector => | |
233 | 239 | vrf | |
234 | 240 | case _ => | |
235 | 241 | lastBlock.generationSignature | |
236 | 242 | } | |
237 | 243 | func processMiner (prev,miner) = { | |
238 | - | let $ | |
239 | - | let prevMiner = $ | |
240 | - | let prevTotalBalance = $ | |
241 | - | let prevDelay = $ | |
242 | - | let prevMiners = $ | |
244 | + | let $t079778040 = prev | |
245 | + | let prevMiner = $t079778040._1 | |
246 | + | let prevTotalBalance = $t079778040._2 | |
247 | + | let prevDelay = $t079778040._3 | |
248 | + | let prevMiners = $t079778040._4 | |
243 | 249 | let minerAddress = addressFromStringValue(miner) | |
244 | 250 | let wavesGenBalance = wavesBalance(minerAddress).generating | |
245 | 251 | let minerBalance = generatingBalance(minerAddress) | |
246 | 252 | if (if ((MIN_BALANCE > wavesGenBalance)) | |
247 | 253 | then true | |
248 | 254 | else (0 >= minerBalance)) | |
249 | 255 | then prev | |
250 | 256 | else { | |
251 | 257 | let nextDelay = calculateDelay(minerAddress, minerBalance) | |
252 | 258 | if ((prevDelay > nextDelay)) | |
253 | 259 | then $Tuple4(miner, (prevTotalBalance + minerBalance), nextDelay, (prevMiners :+ miner)) | |
254 | 260 | else $Tuple4(prevMiner, (prevTotalBalance + minerBalance), prevDelay, (prevMiners :+ miner)) | |
255 | 261 | } | |
256 | 262 | } | |
257 | 263 | ||
258 | 264 | let $l = allMiners | |
259 | 265 | let $s = size($l) | |
260 | 266 | let $acc0 = $Tuple4("", 0, INT_MAX, nil) | |
261 | 267 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
262 | 268 | then $a | |
263 | 269 | else processMiner($a, $l[$i]) | |
264 | 270 | ||
265 | 271 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
266 | 272 | then $a | |
267 | 273 | else throw("List size exceeds 50") | |
268 | 274 | ||
269 | 275 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50) | |
270 | 276 | } | |
271 | 277 | ||
272 | - | let computedGenerator = $ | |
278 | + | let computedGenerator = $t077108645._1 | |
273 | 279 | ||
274 | - | let computedTotalBalance = $ | |
280 | + | let computedTotalBalance = $t077108645._2 | |
275 | 281 | ||
276 | - | let $ | |
282 | + | let $t086478713 = blockMeta(mainChainLastBlock) | |
277 | 283 | ||
278 | - | let mclbIgnored1 = $ | |
284 | + | let mclbIgnored1 = $t086478713._1 | |
279 | 285 | ||
280 | - | let mainChainEpoch = $ | |
286 | + | let mainChainEpoch = $t086478713._2 | |
281 | 287 | ||
282 | - | func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = { | |
283 | - | let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "") | |
288 | + | func calculateFinalizedBlockHashAndEpoch (curMiner,curPrevEpoch,curLastBlockHash) = { | |
284 | 289 | let halfBalance = (computedTotalBalance / 2) | |
285 | 290 | func step (prev,next) = { | |
286 | - | let $ | |
287 | - | let thisEpoch = $ | |
288 | - | let | |
289 | - | let totalBalance = $ | |
290 | - | let prevMiners = $ | |
291 | - | match | |
291 | + | let $t089519024 = prev | |
292 | + | let thisEpoch = $t089519024._1 | |
293 | + | let maybeFinalizedBlockHash = $t089519024._2 | |
294 | + | let totalBalance = $t089519024._3 | |
295 | + | let prevMiners = $t089519024._4 | |
296 | + | match maybeFinalizedBlockHash { | |
292 | 297 | case _: Unit => | |
293 | - | let $ | |
298 | + | let $t090919257 = if ((thisEpoch == height)) | |
294 | 299 | then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash) | |
295 | 300 | else value(epochMeta(thisEpoch)) | |
296 | - | let miner = $ | |
297 | - | let prevEpoch = $ | |
298 | - | let lastBlockHash = $ | |
301 | + | let miner = $t090919257._1 | |
302 | + | let prevEpoch = $t090919257._2 | |
303 | + | let lastBlockHash = $t090919257._3 | |
299 | 304 | if (if ((prevEpoch == 0)) | |
300 | 305 | then true | |
301 | 306 | else ((height - thisEpoch) >= 100)) | |
302 | 307 | then $Tuple4(thisEpoch, lastBlockHash, totalBalance, allMiners) | |
303 | 308 | else { | |
304 | - | let $ | |
309 | + | let $t094119613 = if (containsElement(prevMiners, miner)) | |
305 | 310 | then $Tuple2(totalBalance, prevMiners) | |
306 | 311 | else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners) | |
307 | - | let newTotalBalance = $ | |
308 | - | let newMiners = $ | |
312 | + | let newTotalBalance = $t094119613._1 | |
313 | + | let newMiners = $t094119613._2 | |
309 | 314 | if ((newTotalBalance > halfBalance)) | |
310 | 315 | then $Tuple4(thisEpoch, lastBlockHash, newTotalBalance, allMiners) | |
311 | 316 | else $Tuple4(prevEpoch, unit, newTotalBalance, newMiners) | |
312 | 317 | } | |
313 | 318 | case _ => | |
314 | 319 | prev | |
315 | 320 | } | |
316 | 321 | } | |
317 | 322 | ||
318 | - | let $ | |
323 | + | let $t098469943 = { | |
319 | 324 | let $l = offsets_100 | |
320 | 325 | let $s = size($l) | |
321 | 326 | let $acc0 = $Tuple4(height, unit, 0, nil) | |
322 | 327 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
323 | 328 | then $a | |
324 | 329 | else step($a, $l[$i]) | |
325 | 330 | ||
326 | 331 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
327 | 332 | then $a | |
328 | 333 | else throw("List size exceeds 100") | |
329 | 334 | ||
330 | 335 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
331 | 336 | } | |
332 | - | let | |
333 | - | let finalizedBlockHashOpt = $ | |
334 | - | match finalizedBlockHashOpt { | |
337 | + | let finalizedEpoch = $t098469943._1 | |
338 | + | let finalizedBlockHashOpt = $t098469943._2 | |
339 | + | $Tuple2( match finalizedBlockHashOpt { | |
335 | 340 | case finalizedBlockHash: String => | |
336 | 341 | finalizedBlockHash | |
337 | 342 | case _ => | |
338 | - | value(epochMeta( | |
339 | - | } | |
343 | + | value(epochMeta(finalizedEpoch))._3 | |
344 | + | }, finalizedEpoch) | |
340 | 345 | } | |
341 | 346 | ||
342 | 347 | ||
343 | 348 | func supportingBalance (chainId) = { | |
344 | 349 | func addBalance (acc,generatorStr) = { | |
345 | - | let $ | |
346 | - | let totalBalance = $ | |
347 | - | let generators = $ | |
350 | + | let $t01022610262 = acc | |
351 | + | let totalBalance = $t01022610262._1 | |
352 | + | let generators = $t01022610262._2 | |
348 | 353 | let generator = addressFromStringValue(generatorStr) | |
349 | 354 | if (containsElement(generators, generator)) | |
350 | 355 | then acc | |
351 | 356 | else { | |
352 | 357 | let balance = generatingBalance(generator) | |
353 | 358 | $Tuple2((totalBalance + balance), (generators :+ generator)) | |
354 | 359 | } | |
355 | 360 | } | |
356 | 361 | ||
357 | 362 | let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP) | |
358 | - | let | |
363 | + | let res = { | |
359 | 364 | let $l = allGenerators | |
360 | 365 | let $s = size($l) | |
361 | 366 | let $acc0 = $Tuple2(0, nil) | |
362 | 367 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
363 | 368 | then $a | |
364 | 369 | else addBalance($a, $l[$i]) | |
365 | 370 | ||
366 | 371 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
367 | 372 | then $a | |
368 | 373 | else throw("List size exceeds 100") | |
369 | 374 | ||
370 | 375 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
371 | 376 | } | |
372 | - | let balance = $t01046010525._1 | |
373 | - | let _g = $t01046010525._2 | |
374 | - | balance | |
377 | + | res._1 | |
375 | 378 | } | |
376 | 379 | ||
377 | 380 | ||
378 | 381 | func isContractSetup () = isDefined(getInteger(minerRewardKey)) | |
379 | 382 | ||
380 | 383 | ||
381 | 384 | func ensureMiningEpoch (generator) = if ((toString(generator) != computedGenerator)) | |
382 | 385 | then throw(((((toBase58String(generator.bytes) + " is not allowed to mine in ") + toString(height)) + " epoch. Expected ") + computedGenerator)) | |
383 | 386 | else unit | |
384 | 387 | ||
385 | 388 | ||
386 | 389 | func isReferenceCorrect (reference,lastBlock) = if ((reference == lastBlock)) | |
387 | 390 | then unit | |
388 | 391 | else throw(((("Expected a reference to the chain last block: 0x" + lastBlock) + ". Got: 0x") + reference)) | |
389 | 392 | ||
390 | 393 | ||
391 | 394 | func chainIsInactive (chainId) = { | |
392 | 395 | let firstBlockId = getStringValue(chainFirstBlockIdKey(chainId)) | |
393 | 396 | let firstValidAltChainId = valueOrElse(getInteger(firstValidAltChainIdKey), 0) | |
394 | 397 | if ((firstValidAltChainId > chainId)) | |
395 | 398 | then true | |
396 | 399 | else (blockMeta(getStringValue(finalizedBlockKey))._1 > blockMeta(firstBlockId)._1) | |
397 | 400 | } | |
398 | 401 | ||
399 | 402 | ||
400 | 403 | func minerChainId (miner) = valueOrElse(getInteger(minerChainIdKey(miner)), getInteger(("chainIdOf" + toString(miner)))) | |
401 | 404 | ||
402 | 405 | ||
403 | 406 | func ensureExpectedOrInactiveChain (generator,expectedChainId,checkHeightBlock) = { | |
404 | 407 | let heightIsCorrect = match checkHeightBlock { | |
405 | 408 | case blockHash: String => | |
406 | 409 | let lastMinedBlockHeight = lastHeightBy(generator, mainChainId) | |
407 | 410 | ((blockMeta(blockHash)._1 + 1) > lastMinedBlockHeight) | |
408 | 411 | case _ => | |
409 | 412 | true | |
410 | 413 | } | |
411 | 414 | match minerChainId(generator) { | |
412 | 415 | case currentId: Int => | |
413 | 416 | if (if ((currentId == expectedChainId)) | |
414 | 417 | then true | |
415 | 418 | else if (chainIsInactive(currentId)) | |
416 | 419 | then heightIsCorrect | |
417 | 420 | else false) | |
418 | 421 | then unit | |
419 | 422 | else throw(("miner is mining other chain " + toString(currentId))) | |
420 | 423 | case _ => | |
421 | 424 | unit | |
422 | 425 | } | |
423 | 426 | } | |
424 | 427 | ||
425 | 428 | ||
426 | 429 | let heightString = (" at height " + toString(height)) | |
427 | 430 | ||
428 | 431 | func vrfAt (height) = valueOrErrorMessage(valueOrErrorMessage(blockInfoByHeight(height), ("last block is not available" + heightString)).vrf, ("VRF is not available" + heightString)) | |
429 | 432 | ||
430 | 433 | ||
431 | 434 | func ensureCorrectEpoch (expectedVRF) = { | |
432 | 435 | let actualVRF = vrfAt(height) | |
433 | 436 | if ((expectedVRF == actualVRF)) | |
434 | 437 | then unit | |
435 | 438 | else throw((((("Expected VRF " + toBase58String(expectedVRF)) + " does not match actual ") + toBase58String(actualVRF)) + heightString)) | |
436 | 439 | } | |
437 | 440 | ||
438 | 441 | ||
439 | 442 | func addSupporter (chainId,generator) = { | |
440 | 443 | let supportersStr = getStringValue(supportersKey(chainId)) | |
441 | 444 | let supporters = split_4C(supportersStr, SEP) | |
442 | 445 | if (containsElement(supporters, toString(generator))) | |
443 | 446 | then nil | |
444 | 447 | else [StringEntry(supportersKey(chainId), ((supportersStr + SEP) + toString(generator)))] | |
445 | 448 | } | |
446 | 449 | ||
447 | 450 | ||
448 | 451 | func setOrFail (flags,index) = if ((0 > index)) | |
449 | 452 | then throw(("Can't withdraw at negative index: " + toString(index))) | |
450 | 453 | else { | |
451 | 454 | let flagsSize = size(flags) | |
452 | 455 | if ((index >= flagsSize)) | |
453 | 456 | then { | |
454 | 457 | let addZeroes = (index - flagsSize) | |
455 | 458 | if ((addZeroes > size(zeroesStr))) | |
456 | 459 | then throw((("Can't add " + toString(addZeroes)) + " empty flags. Contact with developers")) | |
457 | 460 | else ((flags + take(zeroesStr, addZeroes)) + "1") | |
458 | 461 | } | |
459 | 462 | else { | |
460 | 463 | let tail = drop(flags, index) | |
461 | 464 | let atIndex = take(tail, 1) | |
462 | 465 | if ((atIndex == "0")) | |
463 | 466 | then ((take(flags, index) + "1") + drop(tail, 1)) | |
464 | 467 | else throw((("Transfer #" + toString(index)) + " has been already taken")) | |
465 | 468 | } | |
466 | 469 | } | |
467 | 470 | ||
468 | 471 | ||
469 | 472 | func validateBlockHash (hexStr) = { | |
470 | 473 | let decodedBytes = fromBase16String(hexStr) | |
471 | 474 | if ((size(decodedBytes) != BLOCK_HASH_SIZE)) | |
472 | 475 | then throw("invalid block id length") | |
473 | 476 | else hexStr | |
474 | 477 | } | |
475 | 478 | ||
476 | 479 | ||
477 | 480 | func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = { | |
478 | - | let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1 | |
479 | - | let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex) | |
480 | - | if (if ((newFinalizedBlockHash == newBlockHashHex)) | |
481 | + | let curFinalizedBlockMeta = blockMeta(getStringValue(finalizedBlockKey)) | |
482 | + | let $t01427314393 = calculateFinalizedBlockHashAndEpoch(caller, prevEpoch, newBlockHashHex) | |
483 | + | let newFinalizedBlockHash = $t01427314393._1 | |
484 | + | let newFinalizedEpoch = $t01427314393._2 | |
485 | + | let rewardActions = match getString(daoAddressKey) { | |
486 | + | case addr: String => | |
487 | + | if ((newFinalizedEpoch == curFinalizedBlockMeta._2)) | |
488 | + | then nil | |
489 | + | else { | |
490 | + | func countNonEmptyEpochs (acc,next) = if ((acc._1 == curFinalizedBlockMeta._2)) | |
491 | + | then acc | |
492 | + | else match epochMeta(acc._1) { | |
493 | + | case m: (Address, Int, String) => | |
494 | + | $Tuple2(m._2, (acc._2 + 1)) | |
495 | + | case _ => | |
496 | + | acc | |
497 | + | } | |
498 | + | ||
499 | + | let startFromEpoch = if ((newFinalizedEpoch == height)) | |
500 | + | then prevEpoch | |
501 | + | else valueOrErrorMessage(epochMeta(newFinalizedEpoch), "no prev epoch for start")._2 | |
502 | + | let daoRewards = { | |
503 | + | let $l = offsets_100 | |
504 | + | let $s = size($l) | |
505 | + | let $acc0 = $Tuple2(startFromEpoch, 1) | |
506 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
507 | + | then $a | |
508 | + | else countNonEmptyEpochs($a, $l[$i]) | |
509 | + | ||
510 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
511 | + | then $a | |
512 | + | else throw("List size exceeds 100") | |
513 | + | ||
514 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
515 | + | } | |
516 | + | let reissueAmount = (daoRewards._2 * getIntegerValue(daoRewardKey)) | |
517 | + | let tokenId = fromBase58String(getStringValue(tokenIdKey)) | |
518 | + | [Reissue(tokenId, reissueAmount, true), ScriptTransfer(Address(fromBase58String(addr)), reissueAmount, tokenId)] | |
519 | + | } | |
520 | + | case _ => | |
521 | + | nil | |
522 | + | } | |
523 | + | (rewardActions ++ (if (if ((newFinalizedBlockHash == newBlockHashHex)) | |
481 | 524 | then true | |
482 | - | else (blockMeta(newFinalizedBlockHash)._1 > | |
525 | + | else (blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockMeta._1)) | |
483 | 526 | then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)] | |
484 | - | else nil | |
527 | + | else nil)) | |
485 | 528 | } | |
486 | 529 | ||
487 | 530 | ||
488 | 531 | @Callable(i) | |
489 | 532 | func extendMainChain (blockHashHex,referenceHex,vrf,e2cTransfersRootHashHex,lastC2ETransferIndex) = { | |
490 | 533 | let checkBlockHash = validateBlockHash(blockHashHex) | |
491 | 534 | if ((checkBlockHash == checkBlockHash)) | |
492 | 535 | then { | |
493 | 536 | let checkEpoch = ensureCorrectEpoch(vrf) | |
494 | 537 | if ((checkEpoch == checkEpoch)) | |
495 | 538 | then { | |
496 | 539 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit) | |
497 | 540 | if ((checkChain == checkChain)) | |
498 | 541 | then { | |
499 | 542 | let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock) | |
500 | 543 | if ((checkReference == checkReference)) | |
501 | 544 | then { | |
502 | 545 | let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastC2ETransferIndex, true) | |
503 | 546 | if ((checkTransfers == checkTransfers)) | |
504 | 547 | then { | |
505 | 548 | let thisEpochMeta = match epochMeta(height) { | |
506 | 549 | case _: Unit => | |
507 | 550 | StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex)) | |
508 | 551 | case other => | |
509 | 552 | throw("Epoch already started") | |
510 | 553 | } | |
511 | 554 | if ((thisEpochMeta == thisEpochMeta)) | |
512 | 555 | then { | |
513 | 556 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
514 | 557 | if ((checkGenerator == checkGenerator)) | |
515 | 558 | then { | |
516 | 559 | let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch) | |
517 | 560 | let newChainHeight = (mainChainHeight + 1) | |
518 | 561 | ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, mainChainId, e2cTransfersRootHashHex, lastC2ETransferIndex), mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock) | |
519 | 562 | } | |
520 | 563 | else throw("Strict value is not equal to itself.") | |
521 | 564 | } | |
522 | 565 | else throw("Strict value is not equal to itself.") | |
523 | 566 | } | |
524 | 567 | else throw("Strict value is not equal to itself.") | |
525 | 568 | } | |
526 | 569 | else throw("Strict value is not equal to itself.") | |
527 | 570 | } | |
528 | 571 | else throw("Strict value is not equal to itself.") | |
529 | 572 | } | |
530 | 573 | else throw("Strict value is not equal to itself.") | |
531 | 574 | } | |
532 | 575 | else throw("Strict value is not equal to itself.") | |
533 | 576 | } | |
534 | 577 | ||
535 | 578 | ||
536 | 579 | ||
537 | 580 | @Callable(i) | |
538 | 581 | func startAltChain (blockHashHex,referenceHex,vrf,e2cTransfersRootHashHex,lastC2ETransferIndex) = { | |
539 | 582 | let checkBlockHash = validateBlockHash(blockHashHex) | |
540 | 583 | if ((checkBlockHash == checkBlockHash)) | |
541 | 584 | then { | |
542 | 585 | let checkEpoch = ensureCorrectEpoch(vrf) | |
543 | 586 | if ((checkEpoch == checkEpoch)) | |
544 | 587 | then { | |
545 | - | let $ | |
546 | - | let refChainHeight = $ | |
547 | - | let refEpoch = $ | |
548 | - | let refIgnored1 = $ | |
549 | - | let refIgnored2 = $ | |
550 | - | let refIgnored3 = $ | |
551 | - | let refTransferIndex = $ | |
588 | + | let $t01729017403 = blockMeta(referenceHex) | |
589 | + | let refChainHeight = $t01729017403._1 | |
590 | + | let refEpoch = $t01729017403._2 | |
591 | + | let refIgnored1 = $t01729017403._3 | |
592 | + | let refIgnored2 = $t01729017403._4 | |
593 | + | let refIgnored3 = $t01729017403._5 | |
594 | + | let refTransferIndex = $t01729017403._6 | |
552 | 595 | let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2 | |
553 | 596 | let epochRef = if ((refEpoch >= finalizedEpoch)) | |
554 | 597 | then refEpoch | |
555 | 598 | else throw((((("Can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized")) | |
556 | 599 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex) | |
557 | 600 | if ((checkChain == checkChain)) | |
558 | 601 | then { | |
559 | 602 | let checkTransfers = ensureCorrectTransfers(refTransferIndex, lastC2ETransferIndex, true) | |
560 | 603 | if ((checkTransfers == checkTransfers)) | |
561 | 604 | then { | |
562 | 605 | let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1) | |
563 | 606 | let newChainHeight = (refChainHeight + 1) | |
564 | 607 | let thisEpochMeta = match epochMeta(height) { | |
565 | 608 | case _: Unit => | |
566 | 609 | StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex)) | |
567 | 610 | case other => | |
568 | 611 | throw("Epoch already started") | |
569 | 612 | } | |
570 | 613 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
571 | 614 | if ((checkGenerator == checkGenerator)) | |
572 | 615 | then [thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, newChainId, e2cTransfersRootHashHex, lastC2ETransferIndex), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), mkChainMetaEntry(newChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)] | |
573 | 616 | else throw("Strict value is not equal to itself.") | |
574 | 617 | } | |
575 | 618 | else throw("Strict value is not equal to itself.") | |
576 | 619 | } | |
577 | 620 | else throw("Strict value is not equal to itself.") | |
578 | 621 | } | |
579 | 622 | else throw("Strict value is not equal to itself.") | |
580 | 623 | } | |
581 | 624 | else throw("Strict value is not equal to itself.") | |
582 | 625 | } | |
583 | 626 | ||
584 | 627 | ||
585 | 628 | ||
586 | 629 | @Callable(i) | |
587 | 630 | func extendAltChain (blockHashHex,referenceHex,vrf,chainId,e2cTransfersRootHashHex,lastC2ETransferIndex) = { | |
588 | 631 | let checkBlockHash = validateBlockHash(blockHashHex) | |
589 | 632 | if ((checkBlockHash == checkBlockHash)) | |
590 | 633 | then { | |
591 | 634 | let checkEpoch = ensureCorrectEpoch(vrf) | |
592 | 635 | if ((checkEpoch == checkEpoch)) | |
593 | 636 | then { | |
594 | 637 | let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId))) | |
595 | 638 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3)) | |
596 | 639 | if ((checkChain == checkChain)) | |
597 | 640 | then { | |
598 | - | let $ | |
599 | - | let chainHeight = $ | |
600 | - | let chainLastBlock = $ | |
641 | + | let $t01971619770 = chainMeta(chainId) | |
642 | + | let chainHeight = $t01971619770._1 | |
643 | + | let chainLastBlock = $t01971619770._2 | |
601 | 644 | let checkReference = isReferenceCorrect(referenceHex, chainLastBlock) | |
602 | 645 | if ((checkReference == checkReference)) | |
603 | 646 | then { | |
604 | 647 | let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastC2ETransferIndex, true) | |
605 | 648 | if ((checkTransfers == checkTransfers)) | |
606 | 649 | then { | |
607 | 650 | let newChainHeight = (chainHeight + 1) | |
608 | 651 | let prevEpoch = blockMeta(referenceHex)._2 | |
609 | 652 | let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2))) | |
610 | 653 | then { | |
611 | 654 | let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0) | |
612 | 655 | let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch) | |
613 | 656 | ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock) | |
614 | 657 | } | |
615 | 658 | else nil | |
616 | 659 | let thisEpochMeta = match epochMeta(height) { | |
617 | 660 | case _: Unit => | |
618 | 661 | StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex)) | |
619 | 662 | case other => | |
620 | 663 | throw("Epoch already started") | |
621 | 664 | } | |
622 | 665 | if ((thisEpochMeta == thisEpochMeta)) | |
623 | 666 | then { | |
624 | 667 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
625 | 668 | if ((checkGenerator == checkGenerator)) | |
626 | 669 | then { | |
627 | 670 | let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil)) | |
628 | 671 | then (valueOrElse(minerChainId(i.originCaller), 0) != chainId) | |
629 | 672 | else false) | |
630 | 673 | then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)] | |
631 | 674 | else nil | |
632 | 675 | ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, chainId, e2cTransfersRootHashHex, lastC2ETransferIndex), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock) | |
633 | 676 | } | |
634 | 677 | else throw("Strict value is not equal to itself.") | |
635 | 678 | } | |
636 | 679 | else throw("Strict value is not equal to itself.") | |
637 | 680 | } | |
638 | 681 | else throw("Strict value is not equal to itself.") | |
639 | 682 | } | |
640 | 683 | else throw("Strict value is not equal to itself.") | |
641 | 684 | } | |
642 | 685 | else throw("Strict value is not equal to itself.") | |
643 | 686 | } | |
644 | 687 | else throw("Strict value is not equal to itself.") | |
645 | 688 | } | |
646 | 689 | else throw("Strict value is not equal to itself.") | |
647 | 690 | } | |
648 | 691 | ||
649 | 692 | ||
650 | 693 | ||
651 | 694 | @Callable(i) | |
652 | 695 | func appendBlock (blockHashHex,referenceHex,e2cTransfersRootHashHex,lastC2ETransferIndex) = { | |
653 | 696 | let checkCaller = if ((thisEpochMiner == i.originCaller)) | |
654 | 697 | then true | |
655 | 698 | else match thisEpochMiner { | |
656 | 699 | case epochMiner: Address => | |
657 | 700 | throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner))) | |
658 | 701 | case _ => | |
659 | 702 | throw("not allowed to forge blocks in this epoch, epoch miner is absent") | |
660 | 703 | } | |
661 | 704 | if ((checkCaller == checkCaller)) | |
662 | 705 | then { | |
663 | 706 | let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId) | |
664 | - | let $ | |
665 | - | let chainHeight = $ | |
666 | - | let lastBlockId = $ | |
707 | + | let $t02211922170 = chainMeta(chainId) | |
708 | + | let chainHeight = $t02211922170._1 | |
709 | + | let lastBlockId = $t02211922170._2 | |
667 | 710 | let checkReference = isReferenceCorrect(referenceHex, lastBlockId) | |
668 | 711 | if ((checkReference == checkReference)) | |
669 | 712 | then { | |
670 | 713 | let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._6, lastC2ETransferIndex, false) | |
671 | 714 | if ((checkTransfers == checkTransfers)) | |
672 | 715 | then { | |
673 | 716 | let newChainHeight = (chainHeight + 1) | |
674 | 717 | let checkBlockHash = validateBlockHash(blockHashHex) | |
675 | 718 | if ((checkBlockHash == checkBlockHash)) | |
676 | 719 | then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, chainId, e2cTransfersRootHashHex, lastC2ETransferIndex), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))] | |
677 | 720 | else throw("Strict value is not equal to itself.") | |
678 | 721 | } | |
679 | 722 | else throw("Strict value is not equal to itself.") | |
680 | 723 | } | |
681 | 724 | else throw("Strict value is not equal to itself.") | |
682 | 725 | } | |
683 | 726 | else throw("Strict value is not equal to itself.") | |
684 | 727 | } | |
685 | 728 | ||
686 | 729 | ||
687 | 730 | ||
688 | 731 | @Callable(i) | |
689 | 732 | func join (rewardAddressHex) = { | |
690 | 733 | func ensureNotOverrideOtherMinerPk (elAddressHex) = match getBinary(minerPkKey(elAddressHex)) { | |
691 | 734 | case pk: ByteVector => | |
692 | 735 | if ((pk == i.originCallerPublicKey)) | |
693 | 736 | then unit | |
694 | 737 | else throw(((("EL miner address " + elAddressHex) + " is already linked with ") + toBase58String(pk))) | |
695 | 738 | case _ => | |
696 | 739 | unit | |
697 | 740 | } | |
698 | 741 | ||
699 | 742 | let parts = split(rewardAddressHex, "0x") | |
700 | 743 | let rewardAddress = fromBase16String(parts[(size(parts) - 1)]) | |
701 | 744 | if (!(isContractSetup())) | |
702 | 745 | then throw("The contract has not yet set up") | |
703 | 746 | else if ((MIN_BALANCE > wavesBalance(i.originCaller).generating)) | |
704 | 747 | then throw(((("Insufficient generating balance: " + toString(wavesBalance(i.originCaller).generating)) + ". Required: ") + toString(MIN_BALANCE))) | |
705 | 748 | else if ((size(rewardAddress) != 20)) | |
706 | 749 | then throw("rewardAddress should be an L2 address") | |
707 | 750 | else if ((size(allMiners) >= 50)) | |
708 | 751 | then throw("too many miners") | |
709 | 752 | else { | |
710 | 753 | func checkExistence (exists,miner) = if (exists) | |
711 | 754 | then true | |
712 | 755 | else (miner == toString(i.originCaller)) | |
713 | 756 | ||
714 | 757 | let alreadyExists = { | |
715 | 758 | let $l = allMiners | |
716 | 759 | let $s = size($l) | |
717 | 760 | let $acc0 = false | |
718 | 761 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
719 | 762 | then $a | |
720 | 763 | else checkExistence($a, $l[$i]) | |
721 | 764 | ||
722 | 765 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
723 | 766 | then $a | |
724 | 767 | else throw("List size exceeds 50") | |
725 | 768 | ||
726 | 769 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50) | |
727 | 770 | } | |
728 | 771 | if (alreadyExists) | |
729 | 772 | then nil | |
730 | 773 | else { | |
731 | 774 | let newMiner = toString(i.originCaller) | |
732 | 775 | let lowercaseRewardAddress = toBase16String(rewardAddress) | |
733 | 776 | let check = ensureNotOverrideOtherMinerPk(lowercaseRewardAddress) | |
734 | 777 | if ((check == check)) | |
735 | 778 | then { | |
736 | 779 | let newMiners = if ((size(allMiners) == 0)) | |
737 | 780 | then newMiner | |
738 | 781 | else ((allMinersStr + SEP) + newMiner) | |
739 | 782 | let deletePrevRewardAddressPk = match getString(minerRewardAddressKey(newMiner)) { | |
740 | 783 | case prevAddress: String => | |
741 | 784 | if ((prevAddress == toBase16String(rewardAddress))) | |
742 | 785 | then nil | |
743 | 786 | else [DeleteEntry(minerPkKey(prevAddress))] | |
744 | 787 | case _ => | |
745 | 788 | nil | |
746 | 789 | } | |
747 | 790 | ([StringEntry(allMinersKey, newMiners), StringEntry(minerRewardAddressKey(newMiner), ("0x" + lowercaseRewardAddress)), BinaryEntry(minerPkKey(lowercaseRewardAddress), i.originCallerPublicKey)] ++ deletePrevRewardAddressPk) | |
748 | 791 | } | |
749 | 792 | else throw("Strict value is not equal to itself.") | |
750 | 793 | } | |
751 | 794 | } | |
752 | 795 | } | |
753 | 796 | ||
754 | 797 | ||
755 | 798 | ||
756 | 799 | @Callable(i) | |
757 | 800 | func leave () = { | |
758 | 801 | let leavingMiner = toString(i.originCaller) | |
759 | 802 | func skipLeavingMiner (acc,miner) = if ((miner == leavingMiner)) | |
760 | 803 | then acc | |
761 | 804 | else (acc :+ miner) | |
762 | 805 | ||
763 | 806 | let remainingMiners = { | |
764 | 807 | let $l = allMiners | |
765 | 808 | let $s = size($l) | |
766 | 809 | let $acc0 = nil | |
767 | 810 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
768 | 811 | then $a | |
769 | 812 | else skipLeavingMiner($a, $l[$i]) | |
770 | 813 | ||
771 | 814 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
772 | 815 | then $a | |
773 | 816 | else throw("List size exceeds 50") | |
774 | 817 | ||
775 | 818 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50) | |
776 | 819 | } | |
777 | 820 | let rewardAddrKey = minerRewardAddressKey(leavingMiner) | |
778 | 821 | let prevRewardAddress = valueOrErrorMessage(getString(this, rewardAddrKey), "miner has never joined") | |
779 | 822 | if ((prevRewardAddress == prevRewardAddress)) | |
780 | 823 | then if ((thisEpochMiner == i.originCaller)) | |
781 | 824 | then throw("designated miner can't leave") | |
782 | 825 | else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP))] | |
783 | 826 | else throw("Strict value is not equal to itself.") | |
784 | 827 | } | |
785 | 828 | ||
786 | 829 | ||
787 | 830 | ||
788 | 831 | @Callable(i) | |
789 | 832 | func transfer (destElAddressHex) = { | |
790 | 833 | let checkAddress = if ((size(destElAddressHex) == ETH_ADDRESS_STR_SIZE)) | |
791 | 834 | then fromBase16String(destElAddressHex) | |
792 | 835 | else throw(((("Address should have " + toString(ETH_ADDRESS_STR_SIZE)) + " characters, got ") + toString(size(destElAddressHex)))) | |
793 | 836 | if ((checkAddress == checkAddress)) | |
794 | 837 | then { | |
795 | 838 | let checkPayment = if ((size(i.payments) == 1)) | |
796 | 839 | then true | |
797 | 840 | else throw(("Expected one payment as a transfer amount, got " + toString(size(i.payments)))) | |
798 | 841 | if ((checkPayment == checkPayment)) | |
799 | 842 | then { | |
800 | 843 | let tokenIdStr = getStringValue(tokenIdKey) | |
801 | 844 | let tokenId = fromBase58String(tokenIdStr) | |
802 | 845 | let t = i.payments[0] | |
803 | 846 | let checkAssetId = match t.assetId { | |
804 | 847 | case assetId: ByteVector => | |
805 | 848 | if ((assetId == tokenId)) | |
806 | 849 | then true | |
807 | 850 | else throw(((("Expected " + tokenIdStr) + " in the payment, got ") + toBase58String(assetId))) | |
808 | 851 | case _ => | |
809 | 852 | throw((("Expected " + tokenIdStr) + " in the payment, got Waves")) | |
810 | 853 | } | |
811 | 854 | if ((checkAssetId == checkAssetId)) | |
812 | 855 | then { | |
813 | 856 | let lastIndex = blockMeta(mainChainLastBlock)._6 | |
814 | 857 | let queueSize = (nativeTransfersCount - lastIndex) | |
815 | 858 | let checkQueueLimit = if ((160 > queueSize)) | |
816 | 859 | then amountGtEq(t, 1000000, queueSize) | |
817 | 860 | else if ((1600 > queueSize)) | |
818 | 861 | then amountGtEq(t, 10000000, queueSize) | |
819 | 862 | else if ((3200 > queueSize)) | |
820 | 863 | then amountGtEq(t, 100000000, queueSize) | |
821 | 864 | else if ((6400 > queueSize)) | |
822 | 865 | then amountGtEq(t, 1000000000, queueSize) | |
823 | 866 | else throw((("Transfers denied for queue size of " + toString(queueSize)) + ". Wait until current transfers processed")) | |
824 | 867 | if ((checkQueueLimit == checkQueueLimit)) | |
825 | 868 | then [IntegerEntry(nativeTransfersCountKey, (nativeTransfersCount + 1)), mkNativeTransferEntry(nativeTransfersCount, destElAddressHex, t.amount), Burn(tokenId, t.amount)] | |
826 | 869 | else throw("Strict value is not equal to itself.") | |
827 | 870 | } | |
828 | 871 | else throw("Strict value is not equal to itself.") | |
829 | 872 | } | |
830 | 873 | else throw("Strict value is not equal to itself.") | |
831 | 874 | } | |
832 | 875 | else throw("Strict value is not equal to itself.") | |
833 | 876 | } | |
834 | 877 | ||
835 | 878 | ||
836 | 879 | ||
837 | 880 | @Callable(i) | |
838 | 881 | func withdraw (blockHashHex,merkleProof,transferIndexInBlock,amount) = { | |
839 | 882 | let withdrawBlockMeta = blockMeta(blockHashHex) | |
840 | 883 | let withdrawBlockHeight = withdrawBlockMeta._1 | |
841 | 884 | let finalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1 | |
842 | 885 | let mainChainLastBlockHeight = blockMeta(mainChainLastBlock)._1 | |
843 | 886 | if ((withdrawBlockHeight > finalizedBlockHeight)) | |
844 | 887 | then throw(((("EL block #" + toString(withdrawBlockHeight)) + " is not finalized. The current finalized is #") + toString(finalizedBlockHeight))) | |
845 | 888 | else if ((size(merkleProof) != WITHDRAW_PROOFS_SIZE)) | |
846 | 889 | then throw(((("Expected " + toString(WITHDRAW_PROOFS_SIZE)) + " proofs, got ") + toString(size(merkleProof)))) | |
847 | 890 | else if ((0 > transferIndexInBlock)) | |
848 | 891 | then throw(("Transfer index in block should be nonnegative, got " + toString(transferIndexInBlock))) | |
849 | 892 | else if ((0 >= amount)) | |
850 | 893 | then throw(("Amount should be positive, got " + toString(amount))) | |
851 | 894 | else { | |
852 | 895 | let withdrawBlockChainId = withdrawBlockMeta._4 | |
853 | 896 | let isMainChain = (withdrawBlockChainId == mainChainId) | |
854 | 897 | let relatesToMainChain = match getInteger(chainForkedHeightKey(withdrawBlockChainId)) { | |
855 | 898 | case forkedHeight: Int => | |
856 | 899 | (forkedHeight > withdrawBlockHeight) | |
857 | 900 | case _ => | |
858 | 901 | throw((((blockHashHex + " is on an alternative chain #") + toString(withdrawBlockChainId)) + " that was not approved by majority. Wait for some blocks")) | |
859 | 902 | } | |
860 | 903 | if (if (isMainChain) | |
861 | 904 | then true | |
862 | 905 | else relatesToMainChain) | |
863 | 906 | then { | |
864 | 907 | let recipient = i.originCaller | |
865 | 908 | let recipientPkHash = take(drop(recipient.bytes, 2), PUBLIC_KEY_HASH_SIZE) | |
866 | 909 | let zeroAmountBytes = base58'11111111111111111111111111111111111111111111' | |
867 | 910 | let amountBytes = toBytes(amount) | |
868 | 911 | let elEventData = ((recipientPkHash + take(zeroAmountBytes, (size(zeroAmountBytes) - size(amountBytes)))) + amountBytes) | |
869 | 912 | let elEventDataDigest = blake2b256_16Kb(elEventData) | |
870 | 913 | let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock) | |
871 | 914 | let expectedRootHash = withdrawBlockMeta._5 | |
872 | 915 | if ((calculatedRootHash == expectedRootHash)) | |
873 | 916 | then { | |
874 | 917 | let tokenId = fromBase58String(getStringValue(tokenIdKey)) | |
875 | 918 | let transfersKey = blockE2CTransfersKey(blockHashHex) | |
876 | 919 | [Reissue(tokenId, amount, true), ScriptTransfer(recipient, amount, tokenId), StringEntry(transfersKey, setOrFail(valueOrElse(getString(transfersKey), ""), transferIndexInBlock))] | |
877 | 920 | } | |
878 | 921 | else throw((((((("Expected root hash: " + toBase16String(expectedRootHash)) + ", got: ") + toBase16String(calculatedRootHash)) + ". Event data digest: ") + toBase64String(elEventDataDigest)) + ". Check your withdraw arguments")) | |
879 | 922 | } | |
880 | 923 | else throw((("Expected " + blockHashHex) + " to be either on the main chain or relate to it")) | |
881 | 924 | } | |
882 | 925 | } | |
883 | 926 | ||
884 | 927 | ||
885 | 928 | ||
886 | 929 | @Callable(i) | |
887 | - | func setup (genesisBlockHashHex,minerRewardInGwei) = if (isContractSetup()) | |
930 | + | func setup (genesisBlockHashHex,minerRewardInGwei,daoAddress,daoReward) = if (isContractSetup()) | |
888 | 931 | then throw("The contract has been already set up") | |
889 | 932 | else if ((0 > minerRewardInGwei)) | |
890 | 933 | then throw("The miner reward must be nonnegative") | |
891 | 934 | else { | |
892 | 935 | let genesisBlockHash = fromBase16String(genesisBlockHashHex) | |
893 | 936 | let checkGenesisBlockHashSize = if ((size(genesisBlockHash) == BLOCK_HASH_SIZE)) | |
894 | 937 | then true | |
895 | 938 | else throw("Wrong genesis block hash") | |
896 | 939 | if ((checkGenesisBlockHashSize == checkGenesisBlockHashSize)) | |
897 | 940 | then { | |
898 | 941 | let emptyPk = base58'11111111111111111111111111111111' | |
899 | 942 | let genesisMinerAddress = addressFromPublicKey(emptyPk) | |
900 | 943 | let genesisEthRewardAddress = base58'11111111111111111111' | |
901 | 944 | let genesisBlockReferenceHash = "0000000000000000000000000000000000000000000000000000000000000000" | |
902 | 945 | let issue = Issue("UNIT0", "Native token", 0, 8, true) | |
903 | 946 | let tokenId = calculateAssetId(issue) | |
904 | 947 | let genesisBlockMeta = mkBlockMetaEntry(genesisBlockHashHex, 0, genesisBlockReferenceHash, 0, toBase16String(base58''), -1) | |
905 | - | [genesisBlockMeta, StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, "0x0000000000000000000000000000000000006a7e")] | |
948 | + | let daoEntries = if ((daoAddress == "")) | |
949 | + | then nil | |
950 | + | else [StringEntry(daoAddressKey, toString(Address(fromBase58String(daoAddress)))), IntegerEntry(daoRewardKey, if ((daoReward > 0)) | |
951 | + | then daoReward | |
952 | + | else throw("invalid DAO reward amount"))] | |
953 | + | ([genesisBlockMeta, StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, "0x0000000000000000000000000000000000006a7e")] ++ daoEntries) | |
906 | 954 | } | |
907 | 955 | else throw("Strict value is not equal to itself.") | |
908 | 956 | } | |
909 | 957 | ||
910 | 958 |
github/deemru/w8io/026f985 130.52 ms ◑