tx · GPDrfDQ2Jpsvk5nSwYoCMcd5MEHcZSCcD2kGPSNpoy1M

3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch:  -0.03900000 Waves

2024.07.17 11:33 [3197802] smart account 3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch > SELF 0.00000000 Waves

{ "type": 13, "id": "GPDrfDQ2Jpsvk5nSwYoCMcd5MEHcZSCcD2kGPSNpoy1M", "fee": 3900000, "feeAssetId": null, "timestamp": 1721205202912, "version": 2, "chainId": 84, "sender": "3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch", "senderPublicKey": "3xjN6fjYDXBGUE1mcRw2Fvr4R6tEZnuJA98QFGF99sXd", "proofs": [ "QoQeusH8EtnYwzXqbgxXGrJcMojwK5Tuf7siG3cDENWuqH6KU1zqjkiYNZPYH46mrhXeXPWzaLVT5wymvA7Fe76" ], "script": "base64:CAJbCAISBAoCCAgSBQoDCAgIEgUKAwgIARIGCgQICAEIEgUKAwgIARIGCgQICAEIEgYKBAEICAESBwoFAQgIAQgSAwoBAhIAEgYKBAgSAQESBgoECAEICBIECgIBCE4AB0lOVF9NQVgA//////////9/AAVXQVZFUwCAwtcvAAtNSU5fQkFMQU5DRQkAaAIAoJwBBQVXQVZFUwADU0VQAgEsAA9CTE9DS19IQVNIX1NJWkUAIAAMQUREUkVTU19TSVpFABoAFFBVQkxJQ19LRVlfSEFTSF9TSVpFABQACXplcm9lc1N0cgKACDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAEHRoaXNFcG9jaERhdGFLZXkCDXRoaXNFcG9jaERhdGEADGFsbE1pbmVyc0tleQIJYWxsTWluZXJzAA5tYWluQ2hhaW5JZEtleQILbWFpbkNoYWluSWQADmxhc3RDaGFpbklkS2V5AgtsYXN0Q2hhaW5JZAAXZmlyc3RWYWxpZEFsdENoYWluSWRLZXkCFGZpcnN0VmFsaWRBbHRDaGFpbklkAA5taW5lclJld2FyZEtleQILbWluZXJSZXdhcmQAGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkCFnN0YWtpbmdDb250cmFjdEFkZHJlc3MACmJsb2NrTWV0YUsCCGJsb2NrXzB4ABFmaW5hbGl6ZWRCbG9ja0tleQIOZmluYWxpemVkQmxvY2sACnRva2VuSWRLZXkCB3Rva2VuSWQAEmVsQnJpZGdlQWRkcmVzc0tleQIPZWxCcmlkZ2VBZGRyZXNzABNwcmV2UmFuZGFvSGVpZ2h0S2V5AhBwcmV2UmFuZGFvSGVpZ2h0ABdlbFRvQ2xUcmFuc2ZlcnNFcG9jaEtleQIUZWxUb0NsVHJhbnNmZXJzRXBvY2gBA3BhZAEBaQQBcwkApAMBBQFpBAckbWF0Y2gwCQCxAgEFAXMDCQAAAgABBQckbWF0Y2gwCQCsAgICBzAwMDAwMDAFAXMDCQAAAgACBQckbWF0Y2gwCQCsAgICBjAwMDAwMAUBcwMJAAACAAMFByRtYXRjaDAJAKwCAgIFMDAwMDAFAXMDCQAAAgAEBQckbWF0Y2gwCQCsAgICBDAwMDAFAXMDCQAAAgAFBQckbWF0Y2gwCQCsAgICAzAwMAUBcwMJAAACAAYFByRtYXRjaDAJAKwCAgICMDAFAXMDCQAAAgAHBQckbWF0Y2gwCQCsAgICATAFAXMFAXMBF2Jsb2NrRWxUb0NsVHJhbnNmZXJzS2V5AQxibG9ja0hhc2hIZXgJAKwCAgISZWxUb0NsVHJhbnNmZXJzXzB4BQxibG9ja0hhc2hIZXgBDGVwb2NoTWV0YUtleQEFZXBvY2gJAKwCAgIGZXBvY2hfCQEDcGFkAQUFZXBvY2gBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQdjaGFpbklkCQCsAgIJAKwCAgIFY2hhaW4JAKQDAQUHY2hhaW5JZAIKRmlyc3RCbG9jawEMY2hhaW5NZXRhS2V5AQdjaGFpbklkCQCsAgICBmNoYWluXwkBA3BhZAEFB2NoYWluSWQBEmNoYWluTGFzdEhlaWdodEtleQIHY2hhaW5JZAVtaW5lcgkArAICCQCsAgIJAKwCAgIGY2hhaW5fCQEDcGFkAQUHY2hhaW5JZAIBXwkApQgBBQVtaW5lcgEUY2hhaW5Gb3JrZWRIZWlnaHRLZXkBB2NoYWluSWQJAKwCAgkArAICAgZjaGFpbl8JAQNwYWQBBQdjaGFpbklkAgxGb3JrZWRIZWlnaHQBDXN1cHBvcnRlcnNLZXkBB2NoYWluSWQJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgpTdXBwb3J0ZXJzARVtaW5lclJld2FyZEFkZHJlc3NLZXkBCW1pbmVyQWRkcgkArAICCQCsAgICBm1pbmVyXwUJbWluZXJBZGRyAg5fUmV3YXJkQWRkcmVzcwEKbWluZXJQa0tleQENcmV3YXJkQWRkcmVzcwkArAICCQCsAgICCG1pbmVyXzB4BQ1yZXdhcmRBZGRyZXNzAgNfUEsBD21pbmVyQ2hhaW5JZEtleQEFbWluZXIJAKwCAgkArAICAgZtaW5lcl8JAKUIAQUFbWluZXICCF9DaGFpbklkABRlbFRvQ2xUcmFuc2ZlcnNFcG9jaAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBRdlbFRvQ2xUcmFuc2ZlcnNFcG9jaEtleQUHSU5UX01BWAEecmVxdWlyZUVsVG9DbFRyYW5zZmVyc0Rpc2FibGVkAAMJAGYCBRRlbFRvQ2xUcmFuc2ZlcnNFcG9jaAUGaGVpZ2h0BQR1bml0CQACAQkArAICCQCsAgICJ0VMIHRvIENMIHRyYW5zZmVycyBhY3RpdmF0ZWQgb24gZXBvY2ggIwkApAMBBQZoZWlnaHQCFS4gVXBncmFkZSB5b3VyIGNsaWVudAEdcmVxdWlyZUVsVG9DbFRyYW5zZmVyc0VuYWJsZWQAAwkAZwIFBmhlaWdodAUUZWxUb0NsVHJhbnNmZXJzRXBvY2gFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAi9FTCB0byBDTCB0cmFuc2ZlcnMgaGF2ZW4ndCBhY3RpdmF0ZWQgb24gZXBvY2ggIwkApAMBBQZoZWlnaHQCGi4gV2FpdCBmb3IgYWN0aXZhdGlvbiBvbiAjCQCkAwEFFGVsVG9DbFRyYW5zZmVyc0Vwb2NoABZzdGFraW5nQ29udHJhY3RBZGRyZXNzBAckbWF0Y2gwCQCdCAIFBHRoaXMFGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUBcwkArAICAiJpbnZhbGlkIHN0YWtpbmcgY29udHJhY3QgYWRkcmVzczogBQFzCQEHQWRkcmVzcwEJARFAZXh0ck5hdGl2ZSgxMDUyKQIFBHRoaXMFGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkBEWdlbmVyYXRpbmdCYWxhbmNlAQdhZGRyZXNzBAckbWF0Y2gwCQCdCAIFFnN0YWtpbmdDb250cmFjdEFkZHJlc3MJAKwCAgIEJXNfXwkApQgBBQdhZGRyZXNzAwkAAQIFByRtYXRjaDACBlN0cmluZwQDc3RyBQckbWF0Y2gwBAlwYXJhbUxpc3QJALUJAgUDc3RyAgJfXwQKcHJldkhlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCXBhcmFtTGlzdAABBAtwcmV2QmFsYW5jZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCXBhcmFtTGlzdAACBApuZXh0SGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJcGFyYW1MaXN0AAMEC25leHRCYWxhbmNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJcGFyYW1MaXN0AAQDCQBnAgUGaGVpZ2h0BQpuZXh0SGVpZ2h0BQtuZXh0QmFsYW5jZQMJAGcCBQZoZWlnaHQFCnByZXZIZWlnaHQFC3ByZXZCYWxhbmNlAAAAAAEJY2hhaW5NZXRhAQdjaGFpbklkBAFzCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEMY2hhaW5NZXRhS2V5AQUHY2hhaW5JZAQFaXRlbXMJALUJAgUBcwUDU0VQCQCUCgIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVpdGVtcwAACQCRAwIFBWl0ZW1zAAEAC21haW5DaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDm1haW5DaGFpbklkS2V5AAAACyR0MDQ5MTE0OTc3CQEJY2hhaW5NZXRhAQULbWFpbkNoYWluSWQAD21haW5DaGFpbkhlaWdodAgFCyR0MDQ5MTE0OTc3Al8xABJtYWluQ2hhaW5MYXN0QmxvY2sIBQskdDA0OTExNDk3NwJfMgEJZXBvY2hNZXRhAQVlcG9jaAQHJG1hdGNoMAkAoggBCQEMZXBvY2hNZXRhS2V5AQUFZXBvY2gDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBAlmcmFnbWVudHMJALUJAgUBcwUDU0VQCQCVCgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUJZnJhZ21lbnRzAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmcmFnbWVudHMAAQkAkQMCBQlmcmFnbWVudHMAAgUEdW5pdAALJHQwNTIwODU2NzIEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIWKEFkZHJlc3MsIEludCwgU3RyaW5nKQQBbQUHJG1hdGNoMAUBbQQHJG1hdGNoMQkAoggBBRB0aGlzRXBvY2hEYXRhS2V5AwkAAQIFByRtYXRjaDECBlN0cmluZwQQcmF3VGhpc0Vwb2NoRGF0YQUHJG1hdGNoMQQNdGhpc0Vwb2NoRGF0YQkAtQkCBRByYXdUaGlzRXBvY2hEYXRhBQNTRVAECXRoaXNFcG9jaAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDXRoaXNFcG9jaERhdGEAAAkAlQoDAwkAAAIFCXRoaXNFcG9jaAUGaGVpZ2h0CQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFDXRoaXNFcG9jaERhdGEAAQUEdW5pdAAAAgAJAJUKAwUEdW5pdAAAAgAADnRoaXNFcG9jaE1pbmVyCAULJHQwNTIwODU2NzICXzEADHRoaXNFcG9jaFJlZggFCyR0MDUyMDg1NjcyAl8yABJ0aGlzRXBvY2hMYXN0QmxvY2sIBQskdDA1MjA4NTY3MgJfMwAMYWxsTWluZXJzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFDGFsbE1pbmVyc0tleQIAAAlhbGxNaW5lcnMEByRtYXRjaDAFDGFsbE1pbmVyc1N0cgMJAAACAgAFByRtYXRjaDAFA25pbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEA3JhdwUHJG1hdGNoMAkAvAkCBQNyYXcFA1NFUAkAAgECC01hdGNoIGVycm9yAQlibG9ja01ldGEBB2Jsb2NrSWQEBG1ldGEJARFAZXh0ck5hdGl2ZSgxMDU3KQEJAKwCAgUKYmxvY2tNZXRhSwUHYmxvY2tJZAQLYmxvY2tIZWlnaHQJALEJAQUEbWV0YQQKYmxvY2tFcG9jaAkAsgkCBQRtZXRhAAgEC2Jsb2NrUGFyZW50CQDJAQIJAMoBAgUEbWV0YQAQBQ9CTE9DS19IQVNIX1NJWkUEDmJsb2NrR2VuZXJhdG9yCQDJAQIJAMoBAgUEbWV0YQkAZAIAEAUPQkxPQ0tfSEFTSF9TSVpFBQxBRERSRVNTX1NJWkUDCQBmAgUUZWxUb0NsVHJhbnNmZXJzRXBvY2gFCmJsb2NrRXBvY2gJAJgKBgULYmxvY2tIZWlnaHQFCmJsb2NrRXBvY2gFC2Jsb2NrUGFyZW50BQ5ibG9ja0dlbmVyYXRvcgAAAQAEB2NoYWluSWQJALEJAQkAygECBQRtZXRhCQBkAgkAZAIAEAUPQkxPQ0tfSEFTSF9TSVpFBQxBRERSRVNTX1NJWkUEF2VsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoCQDKAQIFBG1ldGEJAGQCCQBkAgAYBQ9CTE9DS19IQVNIX1NJWkUFDEFERFJFU1NfU0laRQkAmAoGBQtibG9ja0hlaWdodAUKYmxvY2tFcG9jaAULYmxvY2tQYXJlbnQFDmJsb2NrR2VuZXJhdG9yBQdjaGFpbklkBRdlbFRvQ2xUcmFuc2ZlcnNSb290SGFzaAEQbWtCbG9ja01ldGFFbnRyeQYMYmxvY2tIYXNoSGV4C2Jsb2NrSGVpZ2h0DmJsb2NrUGFyZW50SGV4DmJsb2NrR2VuZXJhdG9yB2NoYWluSWQaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgED2Jsb2NrRXBvY2hCeXRlcwkAmgMBBQZoZWlnaHQEDmJsb2NrTWV0YUJ5dGVzCQDLAQIJAMsBAgkAywECCQDLAQIJAMsBAgkAmgMBBQtibG9ja0hlaWdodAUPYmxvY2tFcG9jaEJ5dGVzCQDdBAEFDmJsb2NrUGFyZW50SGV4CAUOYmxvY2tHZW5lcmF0b3IFYnl0ZXMJAJoDAQUHY2hhaW5JZAkA3QQBBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAkBC0JpbmFyeUVudHJ5AgkArAICBQpibG9ja01ldGFLBQxibG9ja0hhc2hIZXgFDmJsb2NrTWV0YUJ5dGVzAQxsYXN0SGVpZ2h0QnkCBW1pbmVyB2NoYWluSWQEByRtYXRjaDAJAJ8IAQkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQFBW1pbmVyAwkAAQIFByRtYXRjaDACA0ludAQBaAUHJG1hdGNoMAUBaAQJYmxvY2tIYXNoCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgtMYXN0TWluZWRCeQkApQgBBQVtaW5lcggJAQlibG9ja01ldGEBBQlibG9ja0hhc2gCXzEACyR0MDczMjA4Mjg2BAloaXRTb3VyY2UEByRtYXRjaDAIBQlsYXN0QmxvY2sDdnJmAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEA3ZyZgUHJG1hdGNoMAUDdnJmCAUJbGFzdEJsb2NrE2dlbmVyYXRpb25TaWduYXR1cmUKAQxwcm9jZXNzTWluZXICBHByZXYFbWluZXIECyR0MDc2MTg3NjgxBQRwcmV2BAlwcmV2RGVsYXkIBQskdDA3NjE4NzY4MQJfMQQJcHJldk1pbmVyCAULJHQwNzYxODc2ODECXzIEEHByZXZUb3RhbEJhbGFuY2UIBQskdDA3NjE4NzY4MQJfMwQKcHJldk1pbmVycwgFCyR0MDc2MTg3NjgxAl80BAxtaW5lckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBW1pbmVyBA93YXZlc0dlbkJhbGFuY2UICQDvBwEFDG1pbmVyQWRkcmVzcwpnZW5lcmF0aW5nBAxtaW5lckJhbGFuY2UJARFnZW5lcmF0aW5nQmFsYW5jZQEFDG1pbmVyQWRkcmVzcwMDCQBmAgULTUlOX0JBTEFOQ0UFD3dhdmVzR2VuQmFsYW5jZQYJAGcCAAAFDG1pbmVyQmFsYW5jZQUEcHJldgQJbmV4dERlbGF5CQCFBwIFDG1pbmVyQWRkcmVzcwUMbWluZXJCYWxhbmNlAwkAZgIFCXByZXZEZWxheQUJbmV4dERlbGF5CQCWCgQFCW5leHREZWxheQUFbWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UJAM0IAgUKcHJldk1pbmVycwUFbWluZXIJAJYKBAUJcHJldkRlbGF5BQlwcmV2TWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UJAM0IAgUKcHJldk1pbmVycwUFbWluZXIKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlgoEBQdJTlRfTUFYAgAAAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQxwcm9jZXNzTWluZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDUwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgANY29tcHV0ZWREZWxheQgFCyR0MDczMjA4Mjg2Al8xABFjb21wdXRlZEdlbmVyYXRvcggFCyR0MDczMjA4Mjg2Al8yABRjb21wdXRlZFRvdGFsQmFsYW5jZQgFCyR0MDczMjA4Mjg2Al8zAA5maWx0ZXJlZE1pbmVycwgFCyR0MDczMjA4Mjg2Al80ARNnZXRDaGFpbkxhc3RCbG9ja0lkAQdjaGFpbklkCAkBCWNoYWluTWV0YQEFB2NoYWluSWQCXzIACyR0MDgzNTI4NDg3CQEJYmxvY2tNZXRhAQUSbWFpbkNoYWluTGFzdEJsb2NrAAxtY2xiSWdub3JlZDEIBQskdDA4MzUyODQ4NwJfMQAObWFpbkNoYWluRXBvY2gIBQskdDA4MzUyODQ4NwJfMgATbWFpbkNoYWluUGFyZW50SGFzaAgFCyR0MDgzNTI4NDg3Al8zABJtYWluQ2hhaW5HZW5lcmF0b3IIBQskdDA4MzUyODQ4NwJfNAAMbWNsYklnbm9yZWQyCAULJHQwODM1Mjg0ODcCXzUADG1jbGJJZ25vcmVkMwgFCyR0MDgzNTI4NDg3Al82ARtjYWxjdWxhdGVGaW5hbGl6ZWRCbG9ja0hhc2gDCGN1ck1pbmVyDGN1clByZXZFcG9jaBBjdXJMYXN0QmxvY2tIYXNoBAtvZmZzZXRzXzEwMAkAvAkCAmQ6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6AgAEC2hhbGZCYWxhbmNlCQBpAgUUY29tcHV0ZWRUb3RhbEJhbGFuY2UAAgoBBHN0ZXACBHByZXYEbmV4dAQLJHQwODg1Mzg5MTcFBHByZXYECXRoaXNFcG9jaAgFCyR0MDg4NTM4OTE3Al8xBAx0b3RhbEJhbGFuY2UIBQskdDA4ODUzODkxNwJfMgQObWF5YmVTYWZlRXBvY2gIBQskdDA4ODUzODkxNwJfMwQKcHJldk1pbmVycwgFCyR0MDg4NTM4OTE3Al80BAckbWF0Y2gwBQ5tYXliZVNhZmVFcG9jaAMJAAECBQckbWF0Y2gwAgRVbml0BAskdDA4OTc1OTE0MQMJAAACBQl0aGlzRXBvY2gFBmhlaWdodAkAlQoDBQhjdXJNaW5lcgUMY3VyUHJldkVwb2NoBRBjdXJMYXN0QmxvY2tIYXNoCQEFdmFsdWUBCQEJZXBvY2hNZXRhAQUJdGhpc0Vwb2NoBAVtaW5lcggFCyR0MDg5NzU5MTQxAl8xBAlwcmV2RXBvY2gIBQskdDA4OTc1OTE0MQJfMgQNbGFzdEJsb2NrSGFzaAgFCyR0MDg5NzU5MTQxAl8zAwkAAAIFCXByZXZFcG9jaAAACQCWCgQFCXRoaXNFcG9jaAUMdG90YWxCYWxhbmNlBQ1sYXN0QmxvY2tIYXNoBQlhbGxNaW5lcnMECyR0MDkyNjY5NDY4AwkBD2NvbnRhaW5zRWxlbWVudAIFCnByZXZNaW5lcnMFBW1pbmVyCQCUCgIFDHRvdGFsQmFsYW5jZQUKcHJldk1pbmVycwkAlAoCCQBkAgUMdG90YWxCYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQVtaW5lcgkAzAgCBQVtaW5lcgUKcHJldk1pbmVycwQPbmV3VG90YWxCYWxhbmNlCAULJHQwOTI2Njk0NjgCXzEECW5ld01pbmVycwgFCyR0MDkyNjY5NDY4Al8yAwkAZgIFD25ld1RvdGFsQmFsYW5jZQULaGFsZkJhbGFuY2UJAJYKBAUJdGhpc0Vwb2NoBQ9uZXdUb3RhbEJhbGFuY2UFDWxhc3RCbG9ja0hhc2gFCWFsbE1pbmVycwkAlgoEBQlwcmV2RXBvY2gFD25ld1RvdGFsQmFsYW5jZQUEdW5pdAUJbmV3TWluZXJzBQRwcmV2BAskdDA5NzAxOTgzNAoAAiRsCQDOCAIFC29mZnNldHNfMTAwBQtvZmZzZXRzXzEwMAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJYKBAUGaGVpZ2h0AAAFBHVuaXQFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEc3RlcAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIVTGlzdCBzaXplIGV4Y2VlZHMgMjAwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAYgBjAGQAZQBmAGcAaABpAGoAawBsAG0AbgBvAHAAcQByAHMAdAB1AHYAdwB4AHkAegB7AHwAfQB+AH8AgAEAgQEAggEAgwEAhAEAhQEAhgEAhwEAiAEAiQEAigEAiwEAjAEAjQEAjgEAjwEAkAEAkQEAkgEAkwEAlAEAlQEAlgEAlwEAmAEAmQEAmgEAmwEAnAEAnQEAngEAnwEAoAEAoQEAogEAowEApAEApQEApgEApwEAqAEAqQEAqgEAqwEArAEArQEArgEArwEAsAEAsQEAsgEAswEAtAEAtQEAtgEAtwEAuAEAuQEAugEAuwEAvAEAvQEAvgEAvwEAwAEAwQEAwgEAwwEAxAEAxQEAxgEAxwEAyAEEDWZhbGxiYWNrRXBvY2gIBQskdDA5NzAxOTgzNAJfMQQMdG90YWxCYWxhbmNlCAULJHQwOTcwMTk4MzQCXzIEFWZpbmFsaXplZEJsb2NrSGFzaE9wdAgFCyR0MDk3MDE5ODM0Al8zBAZtaW5lcnMIBQskdDA5NzAxOTgzNAJfNAQHJG1hdGNoMAUVZmluYWxpemVkQmxvY2tIYXNoT3B0AwkAAQIFByRtYXRjaDACBlN0cmluZwQSZmluYWxpemVkQmxvY2tIYXNoBQckbWF0Y2gwBRJmaW5hbGl6ZWRCbG9ja0hhc2gICQEFdmFsdWUBCQEJZXBvY2hNZXRhAQUNZmFsbGJhY2tFcG9jaAJfMwERc3VwcG9ydGluZ0JhbGFuY2UBB2NoYWluSWQKAQphZGRCYWxhbmNlAgNhY2MMZ2VuZXJhdG9yU3RyBA0kdDAxMDEwNDEwMTQwBQNhY2MEDHRvdGFsQmFsYW5jZQgFDSR0MDEwMTA0MTAxNDACXzEECmdlbmVyYXRvcnMIBQ0kdDAxMDEwNDEwMTQwAl8yBAlnZW5lcmF0b3IJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDGdlbmVyYXRvclN0cgMJAQ9jb250YWluc0VsZW1lbnQCBQpnZW5lcmF0b3JzBQlnZW5lcmF0b3IFA2FjYwQHYmFsYW5jZQkBEWdlbmVyYXRpbmdCYWxhbmNlAQUJZ2VuZXJhdG9yCQCUCgIJAGQCBQx0b3RhbEJhbGFuY2UFB2JhbGFuY2UJAM0IAgUKZ2VuZXJhdG9ycwUJZ2VuZXJhdG9yBA1hbGxHZW5lcmF0b3JzCQC8CQIJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQ1zdXBwb3J0ZXJzS2V5AQUHY2hhaW5JZAUDU0VQBA0kdDAxMDQ2MjEwNTI3CgACJGwFDWFsbEdlbmVyYXRvcnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQphZGRCYWxhbmNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhVMaXN0IHNpemUgZXhjZWVkcyAxMDAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZAQHYmFsYW5jZQgFDSR0MDEwNDYyMTA1MjcCXzEEAl9nCAUNJHQwMTA0NjIxMDUyNwJfMgUHYmFsYW5jZQEPaXNDb250cmFjdFNldHVwAAkBCWlzRGVmaW5lZAEJAJ8IAQUObWluZXJSZXdhcmRLZXkBEWVuc3VyZU1pbmluZ0Vwb2NoAQlnZW5lcmF0b3IDCQECIT0CCQClCAEFCWdlbmVyYXRvcgURY29tcHV0ZWRHZW5lcmF0b3IJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJANgEAQgFCWdlbmVyYXRvcgVieXRlcwIbIGlzIG5vdCBhbGxvd2VkIHRvIG1pbmUgaW4gCQCkAwEFBmhlaWdodAIRIGVwb2NoLiBFeHBlY3RlZCAFEWNvbXB1dGVkR2VuZXJhdG9yBQR1bml0ARJpc1JlZmVyZW5jZUNvcnJlY3QCCXJlZmVyZW5jZQlsYXN0QmxvY2sDCQAAAgUJcmVmZXJlbmNlBQlsYXN0QmxvY2sFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAjBFeHBlY3RlZCBhIHJlZmVyZW5jZSB0byB0aGUgY2hhaW4gbGFzdCBibG9jazogMHgFCWxhc3RCbG9jawIJLiBHb3Q6IDB4BQlyZWZlcmVuY2UBD2NoYWluSXNJbmFjdGl2ZQEHY2hhaW5JZAQMZmlyc3RCbG9ja0lkCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQdjaGFpbklkBBRmaXJzdFZhbGlkQWx0Q2hhaW5JZAkBC3ZhbHVlT3JFbHNlAgkAnwgBBRdmaXJzdFZhbGlkQWx0Q2hhaW5JZEtleQAAAwkAZgIFFGZpcnN0VmFsaWRBbHRDaGFpbklkBQdjaGFpbklkBgkAZgIICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkCXzEICQEJYmxvY2tNZXRhAQUMZmlyc3RCbG9ja0lkAl8xAQxtaW5lckNoYWluSWQBBW1pbmVyCQELdmFsdWVPckVsc2UCCQCfCAEJAQ9taW5lckNoYWluSWRLZXkBBQVtaW5lcgkAnwgBCQCsAgICCWNoYWluSWRPZgkApQgBBQVtaW5lcgEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCWdlbmVyYXRvcg9leHBlY3RlZENoYWluSWQQY2hlY2tIZWlnaHRCbG9jawQPaGVpZ2h0SXNDb3JyZWN0BAckbWF0Y2gwBRBjaGVja0hlaWdodEJsb2NrAwkAAQIFByRtYXRjaDACBlN0cmluZwQJYmxvY2tIYXNoBQckbWF0Y2gwBBRsYXN0TWluZWRCbG9ja0hlaWdodAkBDGxhc3RIZWlnaHRCeQIFCWdlbmVyYXRvcgULbWFpbkNoYWluSWQJAGYCCQBkAggJAQlibG9ja01ldGEBBQlibG9ja0hhc2gCXzEAAQUUbGFzdE1pbmVkQmxvY2tIZWlnaHQGBAckbWF0Y2gwCQEMbWluZXJDaGFpbklkAQUJZ2VuZXJhdG9yAwkAAQIFByRtYXRjaDACA0ludAQJY3VycmVudElkBQckbWF0Y2gwAwMJAAACBQljdXJyZW50SWQFD2V4cGVjdGVkQ2hhaW5JZAYDCQEPY2hhaW5Jc0luYWN0aXZlAQUJY3VycmVudElkBQ9oZWlnaHRJc0NvcnJlY3QHBQR1bml0CQACAQkArAICAhxtaW5lciBpcyBtaW5pbmcgb3RoZXIgY2hhaW4gCQCkAwEFCWN1cnJlbnRJZAUEdW5pdAESZW5zdXJlQ29ycmVjdEVwb2NoAQVlcG9jaAMJAAACBQVlcG9jaAUGaGVpZ2h0BQR1bml0CQACAQkArAICCQCsAgIJAKwCAgIaRXhwZWN0ZWQgYmxvY2sgZnJvbSBlcG9jaCAJAKQDAQUGaGVpZ2h0AgYuIEdvdCAJAKQDAQUFZXBvY2gBDGFkZFN1cHBvcnRlcgIHY2hhaW5JZAlnZW5lcmF0b3IEDXN1cHBvcnRlcnNTdHIJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQ1zdXBwb3J0ZXJzS2V5AQUHY2hhaW5JZAQKc3VwcG9ydGVycwkAvAkCBQ1zdXBwb3J0ZXJzU3RyBQNTRVADCQEPY29udGFpbnNFbGVtZW50AgUKc3VwcG9ydGVycwkApQgBBQlnZW5lcmF0b3IFA25pbAkAzAgCCQELU3RyaW5nRW50cnkCCQENc3VwcG9ydGVyc0tleQEFB2NoYWluSWQJAKwCAgkArAICBQ1zdXBwb3J0ZXJzU3RyBQNTRVAJAKUIAQUJZ2VuZXJhdG9yBQNuaWwBCXNldE9yRmFpbAIFZmxhZ3MFaW5kZXgDCQBmAgAABQVpbmRleAkAAgEJAKwCAgIiQ2FuJ3Qgd2l0aGRyYXcgYXQgbmVnYXRpdmUgaW5kZXg6IAkApAMBBQVpbmRleAQJZmxhZ3NTaXplCQCxAgEFBWZsYWdzAwkAZwIFBWluZGV4BQlmbGFnc1NpemUECWFkZFplcm9lcwkAZQIFBWluZGV4BQlmbGFnc1NpemUDCQBmAgUJYWRkWmVyb2VzCQCxAgEFCXplcm9lc1N0cgkAAgEJAKwCAgkArAICAgpDYW4ndCBhZGQgCQCkAwEFCWFkZFplcm9lcwIlIGVtcHR5IGZsYWdzLiBDb250YWN0IHdpdGggZGV2ZWxvcGVycwkArAICCQCsAgIFBWZsYWdzCQCvAgIFCXplcm9lc1N0cgUJYWRkWmVyb2VzAgExBAR0YWlsCQCwAgIFBWZsYWdzBQVpbmRleAQHYXRJbmRleAkArwICBQR0YWlsAAEDCQAAAgUHYXRJbmRleAIBMAkArAICCQCsAgIJAK8CAgUFZmxhZ3MFBWluZGV4AgExCQCwAgIFBHRhaWwAAQkAAgEJAKwCAgkArAICAgpUcmFuc2ZlciAjCQCkAwEFBWluZGV4AhcgaGFzIGJlZW4gYWxyZWFkeSB0YWtlbgERdmFsaWRhdGVCbG9ja0hhc2gBBmhleFN0cgQMZGVjb2RlZEJ5dGVzCQDdBAEFBmhleFN0cgMJAQIhPQIJAMgBAQUMZGVjb2RlZEJ5dGVzACAJAAIBAhdpbnZhbGlkIGJsb2NrIGlkIGxlbmd0aAUGaGV4U3RyAR1nZXRVcGRhdGVGaW5hbGl6ZWRCbG9ja0FjdGlvbgMGY2FsbGVyD25ld0Jsb2NrSGFzaEhleAlwcmV2RXBvY2gEF2N1ckZpbmFsaXplZEJsb2NrSGVpZ2h0CAkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFEWZpbmFsaXplZEJsb2NrS2V5Al8xBBVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gJARtjYWxjdWxhdGVGaW5hbGl6ZWRCbG9ja0hhc2gDBQZjYWxsZXIFCXByZXZFcG9jaAUPbmV3QmxvY2tIYXNoSGV4AwMJAAACBRVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gFD25ld0Jsb2NrSGFzaEhleAYJAGYCCAkBCWJsb2NrTWV0YQEFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAJfMQUXY3VyRmluYWxpemVkQmxvY2tIZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgURZmluYWxpemVkQmxvY2tLZXkFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAUDbmlsBQNuaWwNAWkBC2FwcGVuZEJsb2NrAgxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BAxjaGVja1ZlcnNpb24JAR5yZXF1aXJlRWxUb0NsVHJhbnNmZXJzRGlzYWJsZWQAAwkAAAIFDGNoZWNrVmVyc2lvbgUMY2hlY2tWZXJzaW9uAwkBAiE9AgUOdGhpc0Vwb2NoTWluZXIIBQFpDG9yaWdpbkNhbGxlcgQHJG1hdGNoMAUOdGhpc0Vwb2NoTWluZXIDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQKZXBvY2hNaW5lcgUHJG1hdGNoMAkAAgEJAKwCAgI5bm90IGFsbG93ZWQgdG8gZm9yZ2UgYmxvY2tzIGluIHRoaXMgZXBvY2gsIGV4cGVjdGVkIGZyb20gCQClCAEFCmVwb2NoTWluZXIJAAIBAkBub3QgYWxsb3dlZCB0byBmb3JnZSBibG9ja3MgaW4gdGhpcyBlcG9jaCwgZXBvY2ggbWluZXIgaXMgYWJzZW50BAdjaGFpbklkCQELdmFsdWVPckVsc2UCCQEMbWluZXJDaGFpbklkAQgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAQNJHQwMTQ2NDQxNDY5NQkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMTQ2NDQxNDY5NQJfMQQLbGFzdEJsb2NrSWQIBQ0kdDAxNDY0NDE0Njk1Al8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAULbGFzdEJsb2NrSWQDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEEDG5ld0Jsb2NrTWV0YQkAywECCQDLAQIJAMsBAgkAmgMBBQ5uZXdDaGFpbkhlaWdodAkAmgMBBQZoZWlnaHQJAN0EAQULbGFzdEJsb2NrSWQICAUBaQxvcmlnaW5DYWxsZXIFYnl0ZXMEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQdjaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKwCAgkArAICCQClCAEJAQV2YWx1ZQEFDnRoaXNFcG9jaE1pbmVyBQNTRVAJAKQDAQUMdGhpc0Vwb2NoUmVmBQNTRVAFDGJsb2NrSGFzaEhleAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmFwcGVuZEJsb2NrX3YyAwxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4GmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4BAxjaGVja1ZlcnNpb24JAR1yZXF1aXJlRWxUb0NsVHJhbnNmZXJzRW5hYmxlZAADCQAAAgUMY2hlY2tWZXJzaW9uBQxjaGVja1ZlcnNpb24DCQECIT0CBQ50aGlzRXBvY2hNaW5lcggFAWkMb3JpZ2luQ2FsbGVyBAckbWF0Y2gwBQ50aGlzRXBvY2hNaW5lcgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAplcG9jaE1pbmVyBQckbWF0Y2gwCQACAQkArAICAjlub3QgYWxsb3dlZCB0byBmb3JnZSBibG9ja3MgaW4gdGhpcyBlcG9jaCwgZXhwZWN0ZWQgZnJvbSAJAKUIAQUKZXBvY2hNaW5lcgkAAgECQG5vdCBhbGxvd2VkIHRvIGZvcmdlIGJsb2NrcyBpbiB0aGlzIGVwb2NoLCBlcG9jaCBtaW5lciBpcyBhYnNlbnQEB2NoYWluSWQJAQt2YWx1ZU9yRWxzZQIJAQxtaW5lckNoYWluSWQBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBA0kdDAxNTk2OTE2MDIwCQEJY2hhaW5NZXRhAQUHY2hhaW5JZAQLY2hhaW5IZWlnaHQIBQ0kdDAxNTk2OTE2MDIwAl8xBAtsYXN0QmxvY2tJZAgFDSR0MDE1OTY5MTYwMjACXzIEDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BQtsYXN0QmxvY2tJZAMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDm5ld0NoYWluSGVpZ2h0CQBkAgULY2hhaW5IZWlnaHQAAQQOY2hlY2tCbG9ja0hhc2gJARF2YWxpZGF0ZUJsb2NrSGFzaAEFDGJsb2NrSGFzaEhleAMJAAACBQ5jaGVja0Jsb2NrSGFzaAUOY2hlY2tCbG9ja0hhc2gJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkGBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BQtsYXN0QmxvY2tJZAgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGNoYWluTWV0YUtleQEFB2NoYWluSWQJAKwCAgkArAICCQCkAwEFDm5ld0NoYWluSGVpZ2h0BQNTRVAFDGJsb2NrSGFzaEhleAkAzAgCCQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQkBBXZhbHVlAQUOdGhpc0Vwb2NoTWluZXIFA1NFUAkApAMBBQx0aGlzRXBvY2hSZWYFA1NFUAUMYmxvY2tIYXNoSGV4BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEPZXh0ZW5kTWFpbkNoYWluAwxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoBAxjaGVja1ZlcnNpb24JAR5yZXF1aXJlRWxUb0NsVHJhbnNmZXJzRGlzYWJsZWQAAwkAAAIFDGNoZWNrVmVyc2lvbgUMY2hlY2tWZXJzaW9uBA5jaGVja0Jsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4AwkAAAIFDmNoZWNrQmxvY2tIYXNoBQ5jaGVja0Jsb2NrSGFzaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFBWVwb2NoAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBQR1bml0AwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4EDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BRJtYWluQ2hhaW5MYXN0QmxvY2sDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQ5tYWluQ2hhaW5FcG9jaAUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkBBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFDm1haW5DaGFpbkVwb2NoBA5uZXdDaGFpbkhlaWdodAkAZAIFD21haW5DaGFpbkhlaWdodAABBAxuZXdCbG9ja01ldGEJAMsBAgkAywECCQDLAQIJAJoDAQUObmV3Q2hhaW5IZWlnaHQJAJoDAQUGaGVpZ2h0CQDdBAEFEm1haW5DaGFpbkxhc3RCbG9jawgIBQFpDG9yaWdpbkNhbGxlcgVieXRlcwkAzggCCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGNoYWluTWV0YUtleQEFC21haW5DaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgUNdGhpc0Vwb2NoTWV0YQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARJleHRlbmRNYWluQ2hhaW5fdjIEDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgFZXBvY2gaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgEDGNoZWNrVmVyc2lvbgkBHXJlcXVpcmVFbFRvQ2xUcmFuc2ZlcnNFbmFibGVkAAMJAAACBQxjaGVja1ZlcnNpb24FDGNoZWNrVmVyc2lvbgQOY2hlY2tCbG9ja0hhc2gJARF2YWxpZGF0ZUJsb2NrSGFzaAEFDGJsb2NrSGFzaEhleAMJAAACBQ5jaGVja0Jsb2NrSGFzaAUOY2hlY2tCbG9ja0hhc2gECmNoZWNrRXBvY2gJARJlbnN1cmVDb3JyZWN0RXBvY2gBBQVlcG9jaAMJAAACBQpjaGVja0Vwb2NoBQpjaGVja0Vwb2NoBA5jaGVja0dlbmVyYXRvcgkBEWVuc3VyZU1pbmluZ0Vwb2NoAQgFAWkMb3JpZ2luQ2FsbGVyAwkAAAIFDmNoZWNrR2VuZXJhdG9yBQ5jaGVja0dlbmVyYXRvcgQKY2hlY2tDaGFpbgkBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUEdW5pdAMJAAACBQpjaGVja0NoYWluBQpjaGVja0NoYWluBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAUSbWFpbkNoYWluTGFzdEJsb2NrAwkAAAIFDmNoZWNrUmVmZXJlbmNlBQ5jaGVja1JlZmVyZW5jZQQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUObWFpbkNoYWluRXBvY2gFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAQUdXBkYXRlRmluYWxpemVkQmxvY2sJAR1nZXRVcGRhdGVGaW5hbGl6ZWRCbG9ja0FjdGlvbgMIBQFpDG9yaWdpbkNhbGxlcgUMYmxvY2tIYXNoSGV4BQ5tYWluQ2hhaW5FcG9jaAQObmV3Q2hhaW5IZWlnaHQJAGQCBQ9tYWluQ2hhaW5IZWlnaHQAAQkAzggCCQDMCAIJARBta0Jsb2NrTWV0YUVudHJ5BgUMYmxvY2tIYXNoSGV4BQ5uZXdDaGFpbkhlaWdodAUSbWFpbkNoYWluTGFzdEJsb2NrCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAkAzAgCCQELU3RyaW5nRW50cnkCCQEMY2hhaW5NZXRhS2V5AQULbWFpbkNoYWluSWQJAKwCAgkArAICCQCkAwEFDm5ld0NoYWluSGVpZ2h0BQNTRVAFDGJsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD21pbmVyQ2hhaW5JZEtleQEIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCBQ10aGlzRXBvY2hNZXRhBQNuaWwFFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDXN0YXJ0QWx0Q2hhaW4DDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgFZXBvY2gEDGNoZWNrVmVyc2lvbgkBHnJlcXVpcmVFbFRvQ2xUcmFuc2ZlcnNEaXNhYmxlZAADCQAAAgUMY2hlY2tWZXJzaW9uBQxjaGVja1ZlcnNpb24EDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEDSR0MDE5Njk4MTk4MDIJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgEDnJlZkNoYWluSGVpZ2h0CAUNJHQwMTk2OTgxOTgwMgJfMQQIcmVmRXBvY2gIBQ0kdDAxOTY5ODE5ODAyAl8yBAZyZWZSZWYIBQ0kdDAxOTY5ODE5ODAyAl8zBAxyZWZHZW5lcmF0b3IIBQ0kdDAxOTY5ODE5ODAyAl80BAtyZWZJZ25vcmVkMQgFDSR0MDE5Njk4MTk4MDICXzUEC3JlZklnbm9yZWQyCAUNJHQwMTk2OTgxOTgwMgJfNgQOZmluYWxpemVkRXBvY2gICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkCXzIECGVwb2NoUmVmAwkAZwIFCHJlZkVwb2NoBQ5maW5hbGl6ZWRFcG9jaAUIcmVmRXBvY2gJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICI2NhbiBub3Qgc3RhcnQgYWx0IGNoYWluIGZyb20gZXBvY2ggCQCkAwEFCHJlZkVwb2NoAggsIGVwb2NoIAkApAMBBQ5maW5hbGl6ZWRFcG9jaAINIGlzIGZpbmFsaXplZAQKY2hlY2tDaGFpbgkBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUMcmVmZXJlbmNlSGV4AwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4ECm5ld0NoYWluSWQJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAAAQQObmV3Q2hhaW5IZWlnaHQJAGQCCAkBCWJsb2NrTWV0YQEFDHJlZmVyZW5jZUhleAJfMQABBAxuZXdCbG9ja01ldGEJAMsBAgkAywECCQDLAQIJAJoDAQUObmV3Q2hhaW5IZWlnaHQJAJoDAQUGaGVpZ2h0CQDdBAEFDHJlZmVyZW5jZUhleAgIBQFpDG9yaWdpbkNhbGxlcgVieXRlcwQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUIZXBvY2hSZWYFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUKbmV3Q2hhaW5JZAUMYmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQpuZXdDaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFCm5ld0NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQpuZXdDaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDXN1cHBvcnRlcnNLZXkBBQpuZXdDaGFpbklkCQClCAEIBQFpDG9yaWdpbkNhbGxlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUObGFzdENoYWluSWRLZXkFCm5ld0NoYWluSWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBzdGFydEFsdENoYWluX3YyBAxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoGmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4BAxjaGVja1ZlcnNpb24JAR1yZXF1aXJlRWxUb0NsVHJhbnNmZXJzRW5hYmxlZAADCQAAAgUMY2hlY2tWZXJzaW9uBQxjaGVja1ZlcnNpb24EDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEDSR0MDIxNjEyMjE3MTYJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgEDnJlZkNoYWluSGVpZ2h0CAUNJHQwMjE2MTIyMTcxNgJfMQQIcmVmRXBvY2gIBQ0kdDAyMTYxMjIxNzE2Al8yBAZyZWZSZWYIBQ0kdDAyMTYxMjIxNzE2Al8zBAxyZWZHZW5lcmF0b3IIBQ0kdDAyMTYxMjIxNzE2Al80BAtyZWZJZ25vcmVkMQgFDSR0MDIxNjEyMjE3MTYCXzUEC3JlZklnbm9yZWQyCAUNJHQwMjE2MTIyMTcxNgJfNgQOZmluYWxpemVkRXBvY2gICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkCXzIECGVwb2NoUmVmAwkAZwIFCHJlZkVwb2NoBQ5maW5hbGl6ZWRFcG9jaAUIcmVmRXBvY2gJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICI2NhbiBub3Qgc3RhcnQgYWx0IGNoYWluIGZyb20gZXBvY2ggCQCkAwEFCHJlZkVwb2NoAggsIGVwb2NoIAkApAMBBQ5maW5hbGl6ZWRFcG9jaAINIGlzIGZpbmFsaXplZAQKY2hlY2tDaGFpbgkBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUMcmVmZXJlbmNlSGV4AwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4ECm5ld0NoYWluSWQJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAAAQQObmV3Q2hhaW5IZWlnaHQJAGQCCAkBCWJsb2NrTWV0YQEFDHJlZmVyZW5jZUhleAJfMQABBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQhlcG9jaFJlZgUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkCQDMCAIFDXRoaXNFcG9jaE1ldGEJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkGBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BQxyZWZlcmVuY2VIZXgIBQFpDG9yaWdpbkNhbGxlcgUKbmV3Q2hhaW5JZAUaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUKbmV3Q2hhaW5JZAUMYmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQpuZXdDaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFCm5ld0NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQpuZXdDaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDXN1cHBvcnRlcnNLZXkBBQpuZXdDaGFpbklkCQClCAEIBQFpDG9yaWdpbkNhbGxlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgUObGFzdENoYWluSWRLZXkFCm5ld0NoYWluSWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5leHRlbmRBbHRDaGFpbgQHY2hhaW5JZAxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoBAxjaGVja1ZlcnNpb24JAR5yZXF1aXJlRWxUb0NsVHJhbnNmZXJzRGlzYWJsZWQAAwkAAAIFDGNoZWNrVmVyc2lvbgUMY2hlY2tWZXJzaW9uBA5jaGVja0Jsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4AwkAAAIFDmNoZWNrQmxvY2tIYXNoBQ5jaGVja0Jsb2NrSGFzaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFBWVwb2NoAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBBNjaGFpbkZpcnN0QmxvY2tNZXRhCQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUHY2hhaW5JZAQKY2hlY2tDaGFpbgkBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkCQDcBAEIBRNjaGFpbkZpcnN0QmxvY2tNZXRhAl8zAwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4EDSR0MDIzOTU1MjQwMDkJAQljaGFpbk1ldGEBBQdjaGFpbklkBAtjaGFpbkhlaWdodAgFDSR0MDIzOTU1MjQwMDkCXzEEDmNoYWluTGFzdEJsb2NrCAUNJHQwMjM5NTUyNDAwOQJfMgQOY2hlY2tSZWZlcmVuY2UJARJpc1JlZmVyZW5jZUNvcnJlY3QCBQxyZWZlcmVuY2VIZXgFDmNoYWluTGFzdEJsb2NrAwkAAAIFDmNoZWNrUmVmZXJlbmNlBQ5jaGVja1JlZmVyZW5jZQQObmV3Q2hhaW5IZWlnaHQJAGQCBQtjaGFpbkhlaWdodAABBAlwcmV2RXBvY2gICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al8yBBN1cGRhdGVNYWluQ2hhaW5EYXRhAwkAZgIJARFzdXBwb3J0aW5nQmFsYW5jZQEFB2NoYWluSWQJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACBAtsYXN0Q2hhaW5JZAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQ5sYXN0Q2hhaW5JZEtleQAABBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFCXByZXZFcG9jaAkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUY2hhaW5Gb3JrZWRIZWlnaHRLZXkBBQttYWluQ2hhaW5JZAgFE2NoYWluRmlyc3RCbG9ja01ldGECXzEJAMwIAgkBDEludGVnZXJFbnRyeQIFDm1haW5DaGFpbklkS2V5BQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdmaXJzdFZhbGlkQWx0Q2hhaW5JZEtleQkAZAIFC2xhc3RDaGFpbklkAAEFA25pbAUUdXBkYXRlRmluYWxpemVkQmxvY2sFA25pbAQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUJcHJldkVwb2NoBQNTRVAFDGJsb2NrSGFzaEhleAQFb3RoZXIFByRtYXRjaDAJAAIBAhVFcG9jaCBhbHJlYWR5IHN0YXJ0ZWQEHXVwZGF0ZU1haW5DaGFpbkxhc3RNaW5lZEJsb2NrAwMJAAACBRN1cGRhdGVNYWluQ2hhaW5EYXRhBQNuaWwJAQIhPQIJAQt2YWx1ZU9yRWxzZQIJAQxtaW5lckNoYWluSWQBCAUBaQxvcmlnaW5DYWxsZXIAAAUHY2hhaW5JZAcJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyCAUTY2hhaW5GaXJzdEJsb2NrTWV0YQJfMQUDbmlsBQNuaWwEDG5ld0Jsb2NrTWV0YQkAywECCQDLAQIJAMsBAgkAmgMBBQ5uZXdDaGFpbkhlaWdodAkAmgMBBQZoZWlnaHQJAN0EAQUMcmVmZXJlbmNlSGV4CAgFAWkMb3JpZ2luQ2FsbGVyBWJ5dGVzCQDOCAIJAM4IAgkAzggCCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGNoYWluTWV0YUtleQEFB2NoYWluSWQJAKwCAgkArAICCQCkAwEFDm5ld0NoYWluSGVpZ2h0BQNTRVAFDGJsb2NrSGFzaEhleAkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPbWluZXJDaGFpbklkS2V5AQgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAUDbmlsBRN1cGRhdGVNYWluQ2hhaW5EYXRhCQEMYWRkU3VwcG9ydGVyAgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBR11cGRhdGVNYWluQ2hhaW5MYXN0TWluZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARFleHRlbmRBbHRDaGFpbl92MgUHY2hhaW5JZAxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoGmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4BAxjaGVja1ZlcnNpb24JAR1yZXF1aXJlRWxUb0NsVHJhbnNmZXJzRW5hYmxlZAADCQAAAgUMY2hlY2tWZXJzaW9uBQxjaGVja1ZlcnNpb24EDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEE2NoYWluRmlyc3RCbG9ja01ldGEJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQdjaGFpbklkBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJANwEAQgFE2NoYWluRmlyc3RCbG9ja01ldGECXzMDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQNJHQwMjY2MTIyNjY2NgkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMjY2MTIyNjY2NgJfMQQOY2hhaW5MYXN0QmxvY2sIBQ0kdDAyNjYxMjI2NjY2Al8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAUOY2hhaW5MYXN0QmxvY2sDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEECXByZXZFcG9jaAgJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgCXzIEE3VwZGF0ZU1haW5DaGFpbkRhdGEDCQBmAgkBEXN1cHBvcnRpbmdCYWxhbmNlAQUHY2hhaW5JZAkAaQIFFGNvbXB1dGVkVG90YWxCYWxhbmNlAAIEC2xhc3RDaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAEFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQEdZ2V0VXBkYXRlRmluYWxpemVkQmxvY2tBY3Rpb24DCAUBaQxvcmlnaW5DYWxsZXIFDGJsb2NrSGFzaEhleAUJcHJldkVwb2NoCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARRjaGFpbkZvcmtlZEhlaWdodEtleQEFC21haW5DaGFpbklkCAUTY2hhaW5GaXJzdEJsb2NrTWV0YQJfMQkAzAgCCQEMSW50ZWdlckVudHJ5AgUObWFpbkNoYWluSWRLZXkFB2NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIFF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5CQBkAgULbGFzdENoYWluSWQAAQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawUDbmlsBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQlwcmV2RXBvY2gFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAQddXBkYXRlTWFpbkNoYWluTGFzdE1pbmVkQmxvY2sDAwkAAAIFE3VwZGF0ZU1haW5DaGFpbkRhdGEFA25pbAkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkBDG1pbmVyQ2hhaW5JZAEIBQFpDG9yaWdpbkNhbGxlcgAABQdjaGFpbklkBwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIIBRNjaGFpbkZpcnN0QmxvY2tNZXRhAl8xBQNuaWwFA25pbAkAzggCCQDOCAIJAM4IAgkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQYFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFDHJlZmVyZW5jZUhleAgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAkAzAgCCQELU3RyaW5nRW50cnkCCQEMY2hhaW5NZXRhS2V5AQUHY2hhaW5JZAkArAICCQCsAgIJAKQDAQUObmV3Q2hhaW5IZWlnaHQFA1NFUAUMYmxvY2tIYXNoSGV4CQDMCAIFDXRoaXNFcG9jaE1ldGEJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQdjaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0BQNuaWwFE3VwZGF0ZU1haW5DaGFpbkRhdGEJAQxhZGRTdXBwb3J0ZXICBQdjaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFHXVwZGF0ZU1haW5DaGFpbkxhc3RNaW5lZEJsb2NrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBGpvaW4BDXJld2FyZEFkZHJlc3MKARJjaGVja1Jld2FyZEFkZHJlc3MBB2FkZHJlc3MEByRtYXRjaDAJAKEIAQkBCm1pbmVyUGtLZXkBBQdhZGRyZXNzAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwAwkAAAIFAnBrCAUBaRVvcmlnaW5DYWxsZXJQdWJsaWNLZXkFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAhFMMiBtaW5lciBhZGRyZXNzIAUHYWRkcmVzcwIYIGlzIGFscmVhZHkgbGlua2VkIHdpdGggCQDYBAEFAnBrBQR1bml0AwkBASEBCQEPaXNDb250cmFjdFNldHVwAAkAAgECH1RoZSBjb250cmFjdCBoYXMgbm90IHlldCBzZXQgdXADCQBmAgULTUlOX0JBTEFOQ0UICQDvBwEIBQFpDG9yaWdpbkNhbGxlcgpnZW5lcmF0aW5nCQACAQkArAICCQCsAgIJAKwCAgIhSW5zdWZmaWNpZW50IGdlbmVyYXRpbmcgYmFsYW5jZTogCQCkAwEICQDvBwEIBQFpDG9yaWdpbkNhbGxlcgpnZW5lcmF0aW5nAgwuIFJlcXVpcmVkOiAJAKQDAQULTUlOX0JBTEFOQ0UDCQECIT0CCQDIAQEFDXJld2FyZEFkZHJlc3MAFAkAAgECJXJld2FyZEFkZHJlc3Mgc2hvdWxkIGJlIGFuIEwyIGFkZHJlc3MDCQBnAgkAkAMBBQlhbGxNaW5lcnMAMgkAAgECD3RvbyBtYW55IG1pbmVycwoBDmNoZWNrRXhpc3RlbmNlAgZleGlzdHMFbWluZXIDBQZleGlzdHMGCQAAAgUFbWluZXIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBA1hbHJlYWR5RXhpc3RzCgACJGwFCWFsbE1pbmVycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAHCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ5jaGVja0V4aXN0ZW5jZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgNTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyAwUNYWxyZWFkeUV4aXN0cwUDbmlsBAhuZXdNaW5lcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEEHJld2FyZEFkZHJlc3NIZXgJANwEAQUNcmV3YXJkQWRkcmVzcwQFY2hlY2sJARJjaGVja1Jld2FyZEFkZHJlc3MBBRByZXdhcmRBZGRyZXNzSGV4AwkAAAIFBWNoZWNrBQVjaGVjawQJbmV3TWluZXJzAwkAAAIJAJADAQUJYWxsTWluZXJzAAAFCG5ld01pbmVyCQCsAgIJAKwCAgUMYWxsTWluZXJzU3RyBQNTRVAFCG5ld01pbmVyBBhkZWxldGVPbGRSZXdhcmRBZGRyZXNzUGsEByRtYXRjaDAJAKIIAQkBFW1pbmVyUmV3YXJkQWRkcmVzc0tleQEFCG5ld01pbmVyAwkAAQIFByRtYXRjaDACBlN0cmluZwQKb2xkQWRkcmVzcwUHJG1hdGNoMAMJAAACBQpvbGRBZGRyZXNzCQDcBAEFDXJld2FyZEFkZHJlc3MFA25pbAkAzAgCCQELRGVsZXRlRW50cnkBCQEKbWluZXJQa0tleQEFCm9sZEFkZHJlc3MFA25pbAUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUMYWxsTWluZXJzS2V5BQluZXdNaW5lcnMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFW1pbmVyUmV3YXJkQWRkcmVzc0tleQEFCG5ld01pbmVyCQCsAgICAjB4BRByZXdhcmRBZGRyZXNzSGV4CQDMCAIJAQtCaW5hcnlFbnRyeQIJAQptaW5lclBrS2V5AQUQcmV3YXJkQWRkcmVzc0hleAgFAWkVb3JpZ2luQ2FsbGVyUHVibGljS2V5BQNuaWwFGGRlbGV0ZU9sZFJld2FyZEFkZHJlc3NQawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQVsZWF2ZQAEDGxlYXZpbmdNaW5lcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIKARBza2lwTGVhdmluZ01pbmVyAgNhY2MFbWluZXIDCQAAAgUFbWluZXIFDGxlYXZpbmdNaW5lcgUDYWNjCQDNCAIFA2FjYwUFbWluZXIED3JlbWFpbmluZ01pbmVycwoAAiRsBQlhbGxNaW5lcnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEHNraXBMZWF2aW5nTWluZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDUwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgQNcmV3YXJkQWRkcktleQkBFW1pbmVyUmV3YXJkQWRkcmVzc0tleQEFDGxlYXZpbmdNaW5lcgQRcHJldlJld2FyZEFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQR0aGlzBQ1yZXdhcmRBZGRyS2V5AhZtaW5lciBoYXMgbmV2ZXIgam9pbmVkAwkAAAIFDnRoaXNFcG9jaE1pbmVyCAUBaQxvcmlnaW5DYWxsZXIJAAIBAhxkZXNpZ25hdGVkIG1pbmVyIGNhbid0IGxlYXZlCQDMCAIJAQtTdHJpbmdFbnRyeQIFDGFsbE1pbmVyc0tleQkAugkCBQ9yZW1haW5pbmdNaW5lcnMFA1NFUAkAzAgCCQELRGVsZXRlRW50cnkBBQ1yZXdhcmRBZGRyS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQptaW5lclBrS2V5AQURcHJldlJld2FyZEFkZHJlc3MFA25pbAFpAQh3aXRoZHJhdwQMYmxvY2tIYXNoSGV4C21lcmtsZVByb29mFHRyYW5zZmVySW5kZXhJbkJsb2NrBmFtb3VudAQPY2hlY2tBY3RpdmF0aW9uCQEdcmVxdWlyZUVsVG9DbFRyYW5zZmVyc0VuYWJsZWQAAwkAAAIFD2NoZWNrQWN0aXZhdGlvbgUPY2hlY2tBY3RpdmF0aW9uBBF3aXRoZHJhd0Jsb2NrTWV0YQkBCWJsb2NrTWV0YQEFDGJsb2NrSGFzaEhleAQTd2l0aGRyYXdCbG9ja0hlaWdodAgFEXdpdGhkcmF3QmxvY2tNZXRhAl8xBBRmaW5hbGl6ZWRCbG9ja0hlaWdodAgJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMQQYbWFpbkNoYWluTGFzdEJsb2NrSGVpZ2h0CAkBCWJsb2NrTWV0YQEFEm1haW5DaGFpbkxhc3RCbG9jawJfMQMJAGYCBRN3aXRoZHJhd0Jsb2NrSGVpZ2h0BRRmaW5hbGl6ZWRCbG9ja0hlaWdodAkAAgEJAKwCAgkArAICCQCsAgICCkVMIGJsb2NrICMJAKQDAQUTd2l0aGRyYXdCbG9ja0hlaWdodAItIGlzIG5vdCBmaW5hbGl6ZWQuIFRoZSBjdXJyZW50IGZpbmFsaXplZCBpcyAjCQCkAwEFFGZpbmFsaXplZEJsb2NrSGVpZ2h0BBR3aXRoZHJhd0Jsb2NrQ2hhaW5JZAgFEXdpdGhkcmF3QmxvY2tNZXRhAl81BAtpc01haW5DaGFpbgkAAAIFFHdpdGhkcmF3QmxvY2tDaGFpbklkBQttYWluQ2hhaW5JZAQScmVsYXRlc1RvTWFpbkNoYWluBAckbWF0Y2gwCQCfCAEJARRjaGFpbkZvcmtlZEhlaWdodEtleQEFFHdpdGhkcmF3QmxvY2tDaGFpbklkAwkAAQIFByRtYXRjaDACA0ludAQMZm9ya2VkSGVpZ2h0BQckbWF0Y2gwCQBmAgUMZm9ya2VkSGVpZ2h0BRN3aXRoZHJhd0Jsb2NrSGVpZ2h0CQACAQkArAICCQCsAgIJAKwCAgUMYmxvY2tIYXNoSGV4Ah0gaXMgb24gYW4gYWx0ZXJuYXRpdmUgY2hhaW4gIwkApAMBBRR3aXRoZHJhd0Jsb2NrQ2hhaW5JZAI4IHRoYXQgd2FzIG5vdCBhcHByb3ZlZCBieSBtYWpvcml0eS4gV2FpdCBmb3Igc29tZSBibG9ja3MDAwULaXNNYWluQ2hhaW4GBRJyZWxhdGVzVG9NYWluQ2hhaW4ECXJlY2lwaWVudAgFAWkMb3JpZ2luQ2FsbGVyBA9yZWNpcGllbnRQa0hhc2gJAMkBAgkAygECCAUJcmVjaXBpZW50BWJ5dGVzAAIFFFBVQkxJQ19LRVlfSEFTSF9TSVpFBA96ZXJvQW1vdW50Qnl0ZXMBLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAthbW91bnRCeXRlcwkAmgMBBQZhbW91bnQEC2VsRXZlbnREYXRhCQDLAQIJAMsBAgUPcmVjaXBpZW50UGtIYXNoCQDJAQIFD3plcm9BbW91bnRCeXRlcwkAZQIJAMgBAQUPemVyb0Ftb3VudEJ5dGVzCQDIAQEFC2Ftb3VudEJ5dGVzBQthbW91bnRCeXRlcwQRZWxFdmVudERhdGFEaWdlc3QJAPAVAQULZWxFdmVudERhdGEEEmNhbGN1bGF0ZWRSb290SGFzaAkAvQUDBQttZXJrbGVQcm9vZgURZWxFdmVudERhdGFEaWdlc3QFFHRyYW5zZmVySW5kZXhJbkJsb2NrBBBleHBlY3RlZFJvb3RIYXNoCAURd2l0aGRyYXdCbG9ja01ldGECXzYDCQAAAgUSY2FsY3VsYXRlZFJvb3RIYXNoBRBleHBlY3RlZFJvb3RIYXNoBAd0b2tlbklkCQDZBAEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFCnRva2VuSWRLZXkEDHRyYW5zZmVyc0tleQkBF2Jsb2NrRWxUb0NsVHJhbnNmZXJzS2V5AQUMYmxvY2tIYXNoSGV4CQDMCAIJAQdSZWlzc3VlAwUHdG9rZW5JZAUGYW1vdW50BgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQlyZWNpcGllbnQFBmFtb3VudAUHdG9rZW5JZAkAzAgCCQELU3RyaW5nRW50cnkCBQx0cmFuc2ZlcnNLZXkJAQlzZXRPckZhaWwCCQELdmFsdWVPckVsc2UCCQCiCAEFDHRyYW5zZmVyc0tleQIABRR0cmFuc2ZlckluZGV4SW5CbG9jawUDbmlsCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFEV4cGVjdGVkIHJvb3QgaGFzaDogCQDcBAEFEGV4cGVjdGVkUm9vdEhhc2gCBywgZ290OiAJANwEAQUSY2FsY3VsYXRlZFJvb3RIYXNoAhUuIEV2ZW50IGRhdGEgZGlnZXN0OiAJANoEAQURZWxFdmVudERhdGFEaWdlc3QJAAIBCQCsAgIJAKwCAgIJRXhwZWN0ZWQgBQxibG9ja0hhc2hIZXgCLyB0byBiZSBlaXRoZXIgb24gdGhlIG1haW4gY2hhaW4gb3IgcmVsYXRlIHRvIGl0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBXNldHVwBBNnZW5lc2lzQmxvY2tIYXNoSGV4EW1pbmVyUmV3YXJkSW5Hd2VpGXN0YWtpbmdDb250cmFjdEFkZHJlc3NCNTgSZWxCcmlkZ2VBZGRyZXNzSGV4AwkBD2lzQ29udHJhY3RTZXR1cAAJAAIBAiRUaGUgY29udHJhY3QgaGFzIGJlZW4gYWxyZWFkeSBzZXQgdXADCQBmAgAABRFtaW5lclJld2FyZEluR3dlaQkAAgECJFRoZSBtaW5lciByZXdhcmQgbXVzdCBiZSBub25uZWdhdGl2ZQQQZ2VuZXNpc0Jsb2NrSGFzaAkA3QQBBRNnZW5lc2lzQmxvY2tIYXNoSGV4BAdlbXB0eVBrASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQTZ2VuZXNpc01pbmVyQWRkcmVzcwkApwgBBQdlbXB0eVBrBBdnZW5lc2lzRXRoUmV3YXJkQWRkcmVzcwEUAAAAAAAAAAAAAAAAAAAAAAAAAAAEGWdlbmVzaXNCbG9ja1JlZmVyZW5jZUhhc2gCQDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAEBWlzc3VlCQDCCAUCBVVOSVQwAgxOYXRpdmUgdG9rZW4AAAAIBgQHdG9rZW5JZAkAuAgBBQVpc3N1ZQkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQYFE2dlbmVzaXNCbG9ja0hhc2hIZXgAAAUZZ2VuZXNpc0Jsb2NrUmVmZXJlbmNlSGFzaAUTZ2VuZXNpc01pbmVyQWRkcmVzcwULbWFpbkNoYWluSWQCAAkAzAgCCQELU3RyaW5nRW50cnkCCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBAAAFE2dlbmVzaXNCbG9ja0hhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGNoYWluTWV0YUtleQEAAAkArAICAgIwLAUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgUObWluZXJSZXdhcmRLZXkFEW1pbmVyUmV3YXJkSW5Hd2VpCQDMCAIJAQtTdHJpbmdFbnRyeQIFGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkFGXN0YWtpbmdDb250cmFjdEFkZHJlc3NCNTgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKUIAQUTZ2VuZXNpc01pbmVyQWRkcmVzcwIDLDAsBRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIFEWZpbmFsaXplZEJsb2NrS2V5BRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNwcmV2UmFuZGFvSGVpZ2h0S2V5AAAJAMwIAgkBDEludGVnZXJFbnRyeQIFF2VsVG9DbFRyYW5zZmVyc0Vwb2NoS2V5AAAJAMwIAgUFaXNzdWUJAMwIAgkBC1N0cmluZ0VudHJ5AgUKdG9rZW5JZEtleQkA2AQBBQd0b2tlbklkCQDMCAIJAQtTdHJpbmdFbnRyeQIFEmVsQnJpZGdlQWRkcmVzc0tleQkArAICAgIweAUSZWxCcmlkZ2VBZGRyZXNzSGV4BQNuaWwBaQEUc2V0dXBFbFRvQ2xUcmFuc2ZlcnMCEGFjdGl2YXRpb25IZWlnaHQSZWxCcmlkZ2VBZGRyZXNzSGV4AwkBCWlzRGVmaW5lZAEJAJ8IAQUXZWxUb0NsVHJhbnNmZXJzRXBvY2hLZXkJAAIBAiVFTCB0byBDTCB0cmFuc2ZlcnMgZmVhdHVyZSB3YXMgc2V0IHVwBAVpc3N1ZQkAwggFAgVVTklUMAIMTmF0aXZlIHRva2VuAAAACAYEB3Rva2VuSWQJALgIAQUFaXNzdWUJAMwIAgkBDEludGVnZXJFbnRyeQIFF2VsVG9DbFRyYW5zZmVyc0Vwb2NoS2V5BRBhY3RpdmF0aW9uSGVpZ2h0CQDMCAIFBWlzc3VlCQDMCAIJAQtTdHJpbmdFbnRyeQIFCnRva2VuSWRLZXkJANgEAQUHdG9rZW5JZAkAzAgCCQELU3RyaW5nRW50cnkCBRJlbEJyaWRnZUFkZHJlc3NLZXkJAKwCAgICMHgFEmVsQnJpZGdlQWRkcmVzc0hleAUDbmlsACfyX+E=", "height": 3197802, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: FNjNKot193WRkSkpK9FPbckjMik1WXVhi6NsfbDPkqLL Next: Eh7NKbyaoxgEJ4BwqmwtiBQho4gcdExwKQ9ZwLmSAcYj Diff:
OldNewDifferences
1212 let BLOCK_HASH_SIZE = 32
1313
1414 let ADDRESS_SIZE = 26
15+
16+let PUBLIC_KEY_HASH_SIZE = 20
17+
18+let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
1519
1620 let thisEpochDataKey = "thisEpochData"
1721
3034 let blockMetaK = "block_0x"
3135
3236 let finalizedBlockKey = "finalizedBlock"
37+
38+let tokenIdKey = "tokenId"
39+
40+let elBridgeAddressKey = "elBridgeAddress"
41+
42+let prevRandaoHeightKey = "prevRandaoHeight"
43+
44+let elToClTransfersEpochKey = "elToClTransfersEpoch"
3345
3446 func pad (i) = {
3547 let s = toString(i)
5466 }
5567
5668
69+func blockElToClTransfersKey (blockHashHex) = ("elToClTransfers_0x" + blockHashHex)
70+
71+
5772 func epochMetaKey (epoch) = ("epoch_" + pad(epoch))
5873
5974
6681 func chainLastHeightKey (chainId,miner) = ((("chain_" + pad(chainId)) + "_") + toString(miner))
6782
6883
84+func chainForkedHeightKey (chainId) = (("chain_" + pad(chainId)) + "ForkedHeight")
85+
86+
6987 func supportersKey (chainId) = (("chain" + toString(chainId)) + "Supporters")
7088
7189
7694
7795
7896 func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId")
97+
98+
99+let elToClTransfersEpoch = valueOrElse(getInteger(this, elToClTransfersEpochKey), INT_MAX)
100+
101+func requireElToClTransfersDisabled () = if ((elToClTransfersEpoch > height))
102+ then unit
103+ else throw((("EL to CL transfers activated on epoch #" + toString(height)) + ". Upgrade your client"))
104+
105+
106+func requireElToClTransfersEnabled () = if ((height >= elToClTransfersEpoch))
107+ then unit
108+ else throw(((("EL to CL transfers haven't activated on epoch #" + toString(height)) + ". Wait for activation on #") + toString(elToClTransfersEpoch)))
79109
80110
81111 let stakingContractAddress = match getString(this, stakingContractAddressKey) {
111141
112142 let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0)
113143
114-let $t028292895 = chainMeta(mainChainId)
144+let $t049114977 = chainMeta(mainChainId)
115145
116-let mainChainHeight = $t028292895._1
146+let mainChainHeight = $t049114977._1
117147
118-let mainChainLastBlock = $t028292895._2
148+let mainChainLastBlock = $t049114977._2
119149
120150 func epochMeta (epoch) = match getString(epochMetaKey(epoch)) {
121151 case s: String =>
126156 }
127157
128158
129-let $t031273591 = match epochMeta(height) {
159+let $t052085672 = match epochMeta(height) {
130160 case m: (Address, Int, String) =>
131161 m
132162 case _ =>
142172 }
143173 }
144174
145-let thisEpochMiner = $t031273591._1
175+let thisEpochMiner = $t052085672._1
146176
147-let thisEpochRef = $t031273591._2
177+let thisEpochRef = $t052085672._2
148178
149-let thisEpochLastBlock = $t031273591._3
179+let thisEpochLastBlock = $t052085672._3
150180
151181 let allMinersStr = valueOrElse(getString(allMinersKey), "")
152182
167197 let blockHeight = toInt(meta)
168198 let blockEpoch = toInt(meta, 8)
169199 let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE)
170- let blockGenerator = takeRight(meta, ADDRESS_SIZE)
171- $Tuple4(blockHeight, blockEpoch, blockParent, blockGenerator)
200+ let blockGenerator = take(drop(meta, (16 + BLOCK_HASH_SIZE)), ADDRESS_SIZE)
201+ if ((elToClTransfersEpoch > blockEpoch))
202+ then $Tuple6(blockHeight, blockEpoch, blockParent, blockGenerator, 0, base58'')
203+ else {
204+ let chainId = toInt(drop(meta, ((16 + BLOCK_HASH_SIZE) + ADDRESS_SIZE)))
205+ let elToClTransfersRootHash = drop(meta, ((24 + BLOCK_HASH_SIZE) + ADDRESS_SIZE))
206+ $Tuple6(blockHeight, blockEpoch, blockParent, blockGenerator, chainId, elToClTransfersRootHash)
207+ }
208+ }
209+
210+
211+func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,blockGenerator,chainId,elToClTransfersRootHashHex) = {
212+ let blockEpochBytes = toBytes(height)
213+ let blockMetaBytes = (((((toBytes(blockHeight) + blockEpochBytes) + fromBase16String(blockParentHex)) + blockGenerator.bytes) + toBytes(chainId)) + fromBase16String(elToClTransfersRootHashHex))
214+ BinaryEntry((blockMetaK + blockHashHex), blockMetaBytes)
172215 }
173216
174217
181224 }
182225
183226
184-let $t043515317 = {
227+let $t073208286 = {
185228 let hitSource = match lastBlock.vrf {
186229 case vrf: ByteVector =>
187230 vrf
189232 lastBlock.generationSignature
190233 }
191234 func processMiner (prev,miner) = {
192- let $t046494712 = prev
193- let prevDelay = $t046494712._1
194- let prevMiner = $t046494712._2
195- let prevTotalBalance = $t046494712._3
196- let prevMiners = $t046494712._4
235+ let $t076187681 = prev
236+ let prevDelay = $t076187681._1
237+ let prevMiner = $t076187681._2
238+ let prevTotalBalance = $t076187681._3
239+ let prevMiners = $t076187681._4
197240 let minerAddress = addressFromStringValue(miner)
198241 let wavesGenBalance = wavesBalance(minerAddress).generating
199242 let minerBalance = generatingBalance(minerAddress)
223266 $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)
224267 }
225268
226-let computedDelay = $t043515317._1
269+let computedDelay = $t073208286._1
227270
228-let computedGenerator = $t043515317._2
271+let computedGenerator = $t073208286._2
229272
230-let computedTotalBalance = $t043515317._3
273+let computedTotalBalance = $t073208286._3
231274
232-let filteredMiners = $t043515317._4
275+let filteredMiners = $t073208286._4
233276
234277 func getChainLastBlockId (chainId) = chainMeta(chainId)._2
235278
236279
237-let $t053835485 = blockMeta(mainChainLastBlock)
280+let $t083528487 = blockMeta(mainChainLastBlock)
238281
239-let ignored = $t053835485._1
282+let mclbIgnored1 = $t083528487._1
240283
241-let mainChainEpoch = $t053835485._2
284+let mainChainEpoch = $t083528487._2
242285
243-let mainChainParentHash = $t053835485._3
286+let mainChainParentHash = $t083528487._3
244287
245-let mainChainGenerator = $t053835485._4
288+let mainChainGenerator = $t083528487._4
289+
290+let mclbIgnored2 = $t083528487._5
291+
292+let mclbIgnored3 = $t083528487._6
246293
247294 func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = {
248295 let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "")
249296 let halfBalance = (computedTotalBalance / 2)
250297 func step (prev,next) = {
251- let $t058515915 = prev
252- let thisEpoch = $t058515915._1
253- let totalBalance = $t058515915._2
254- let maybeSafeEpoch = $t058515915._3
255- let prevMiners = $t058515915._4
298+ let $t088538917 = prev
299+ let thisEpoch = $t088538917._1
300+ let totalBalance = $t088538917._2
301+ let maybeSafeEpoch = $t088538917._3
302+ let prevMiners = $t088538917._4
256303 match maybeSafeEpoch {
257304 case _: Unit =>
258- let $t059736139 = if ((thisEpoch == height))
305+ let $t089759141 = if ((thisEpoch == height))
259306 then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash)
260307 else value(epochMeta(thisEpoch))
261- let miner = $t059736139._1
262- let prevEpoch = $t059736139._2
263- let lastBlockHash = $t059736139._3
308+ let miner = $t089759141._1
309+ let prevEpoch = $t089759141._2
310+ let lastBlockHash = $t089759141._3
264311 if ((prevEpoch == 0))
265312 then $Tuple4(thisEpoch, totalBalance, lastBlockHash, allMiners)
266313 else {
267- let $t062646466 = if (containsElement(prevMiners, miner))
314+ let $t092669468 = if (containsElement(prevMiners, miner))
268315 then $Tuple2(totalBalance, prevMiners)
269316 else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners)
270- let newTotalBalance = $t062646466._1
271- let newMiners = $t062646466._2
317+ let newTotalBalance = $t092669468._1
318+ let newMiners = $t092669468._2
272319 if ((newTotalBalance > halfBalance))
273320 then $Tuple4(thisEpoch, newTotalBalance, lastBlockHash, allMiners)
274321 else $Tuple4(prevEpoch, newTotalBalance, unit, newMiners)
278325 }
279326 }
280327
281- let $t067016834 = {
328+ let $t097019834 = {
282329 let $l = (offsets_100 ++ offsets_100)
283330 let $s = size($l)
284331 let $acc0 = $Tuple4(height, 0, unit, nil)
292339
293340 $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($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 101), 102), 103), 104), 105), 106), 107), 108), 109), 110), 111), 112), 113), 114), 115), 116), 117), 118), 119), 120), 121), 122), 123), 124), 125), 126), 127), 128), 129), 130), 131), 132), 133), 134), 135), 136), 137), 138), 139), 140), 141), 142), 143), 144), 145), 146), 147), 148), 149), 150), 151), 152), 153), 154), 155), 156), 157), 158), 159), 160), 161), 162), 163), 164), 165), 166), 167), 168), 169), 170), 171), 172), 173), 174), 175), 176), 177), 178), 179), 180), 181), 182), 183), 184), 185), 186), 187), 188), 189), 190), 191), 192), 193), 194), 195), 196), 197), 198), 199), 200)
294341 }
295- let fallbackEpoch = $t067016834._1
296- let totalBalance = $t067016834._2
297- let finalizedBlockHashOpt = $t067016834._3
298- let miners = $t067016834._4
342+ let fallbackEpoch = $t097019834._1
343+ let totalBalance = $t097019834._2
344+ let finalizedBlockHashOpt = $t097019834._3
345+ let miners = $t097019834._4
299346 match finalizedBlockHashOpt {
300347 case finalizedBlockHash: String =>
301348 finalizedBlockHash
307354
308355 func supportingBalance (chainId) = {
309356 func addBalance (acc,generatorStr) = {
310- let $t071047140 = acc
311- let totalBalance = $t071047140._1
312- let generators = $t071047140._2
357+ let $t01010410140 = acc
358+ let totalBalance = $t01010410140._1
359+ let generators = $t01010410140._2
313360 let generator = addressFromStringValue(generatorStr)
314361 if (containsElement(generators, generator))
315362 then acc
320367 }
321368
322369 let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP)
323- let $t074627527 = {
370+ let $t01046210527 = {
324371 let $l = allGenerators
325372 let $s = size($l)
326373 let $acc0 = $Tuple2(0, nil)
334381
335382 $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)
336383 }
337- let balance = $t074627527._1
338- let _g = $t074627527._2
384+ let balance = $t01046210527._1
385+ let _g = $t01046210527._2
339386 balance
340387 }
341388
402449 }
403450
404451
452+func setOrFail (flags,index) = if ((0 > index))
453+ then throw(("Can't withdraw at negative index: " + toString(index)))
454+ else {
455+ let flagsSize = size(flags)
456+ if ((index >= flagsSize))
457+ then {
458+ let addZeroes = (index - flagsSize)
459+ if ((addZeroes > size(zeroesStr)))
460+ then throw((("Can't add " + toString(addZeroes)) + " empty flags. Contact with developers"))
461+ else ((flags + take(zeroesStr, addZeroes)) + "1")
462+ }
463+ else {
464+ let tail = drop(flags, index)
465+ let atIndex = take(tail, 1)
466+ if ((atIndex == "0"))
467+ then ((take(flags, index) + "1") + drop(tail, 1))
468+ else throw((("Transfer #" + toString(index)) + " has been already taken"))
469+ }
470+ }
471+
472+
405473 func validateBlockHash (hexStr) = {
406474 let decodedBytes = fromBase16String(hexStr)
407475 if ((size(decodedBytes) != 32))
413481 func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = {
414482 let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
415483 let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex)
416- if ((newFinalizedBlockHash == newBlockHashHex))
484+ if (if ((newFinalizedBlockHash == newBlockHashHex))
485+ then true
486+ else (blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight))
417487 then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)]
418- else if ((blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight))
419- then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)]
420- else nil
488+ else nil
421489 }
422490
423491
424492 @Callable(i)
425-func appendBlock (blockHashHex,referenceHex) = if ((thisEpochMiner != i.originCaller))
426- then match thisEpochMiner {
427- case epochMiner: Address =>
428- throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
429- case _ =>
430- throw("not allowed to forge blocks in this epoch, epoch miner is absent")
493+func appendBlock (blockHashHex,referenceHex) = {
494+ let checkVersion = requireElToClTransfersDisabled()
495+ if ((checkVersion == checkVersion))
496+ then if ((thisEpochMiner != i.originCaller))
497+ then match thisEpochMiner {
498+ case epochMiner: Address =>
499+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
500+ case _ =>
501+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
502+ }
503+ else {
504+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
505+ let $t01464414695 = chainMeta(chainId)
506+ let chainHeight = $t01464414695._1
507+ let lastBlockId = $t01464414695._2
508+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
509+ if ((checkReference == checkReference))
510+ then {
511+ let newChainHeight = (chainHeight + 1)
512+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes)
513+ let checkBlockHash = validateBlockHash(blockHashHex)
514+ if ((checkBlockHash == checkBlockHash))
515+ then [BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
516+ else throw("Strict value is not equal to itself.")
517+ }
518+ else throw("Strict value is not equal to itself.")
519+ }
520+ else throw("Strict value is not equal to itself.")
431521 }
432- else {
433- let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
434- let $t01083310884 = chainMeta(chainId)
435- let chainHeight = $t01083310884._1
436- let lastBlockId = $t01083310884._2
437- let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
438- if ((checkReference == checkReference))
439- then {
440- let newChainHeight = (chainHeight + 1)
441- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes)
442- let blockHash = validateBlockHash(blockHashHex)
443-[BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
522+
523+
524+
525+@Callable(i)
526+func appendBlock_v2 (blockHashHex,referenceHex,elToClTransfersRootHashHex) = {
527+ let checkVersion = requireElToClTransfersEnabled()
528+ if ((checkVersion == checkVersion))
529+ then if ((thisEpochMiner != i.originCaller))
530+ then match thisEpochMiner {
531+ case epochMiner: Address =>
532+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
533+ case _ =>
534+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
535+ }
536+ else {
537+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
538+ let $t01596916020 = chainMeta(chainId)
539+ let chainHeight = $t01596916020._1
540+ let lastBlockId = $t01596916020._2
541+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
542+ if ((checkReference == checkReference))
543+ then {
544+ let newChainHeight = (chainHeight + 1)
545+ let checkBlockHash = validateBlockHash(blockHashHex)
546+ if ((checkBlockHash == checkBlockHash))
547+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
548+ else throw("Strict value is not equal to itself.")
549+ }
550+ else throw("Strict value is not equal to itself.")
444551 }
445- else throw("Strict value is not equal to itself.")
446- }
552+ else throw("Strict value is not equal to itself.")
553+ }
447554
448555
449556
450557 @Callable(i)
451558 func extendMainChain (blockHashHex,referenceHex,epoch) = {
452- let checkEpoch = ensureCorrectEpoch(epoch)
453- if ((checkEpoch == checkEpoch))
559+ let checkVersion = requireElToClTransfersDisabled()
560+ if ((checkVersion == checkVersion))
454561 then {
455- let checkGenerator = ensureMiningEpoch(i.originCaller)
456- if ((checkGenerator == checkGenerator))
562+ let checkBlockHash = validateBlockHash(blockHashHex)
563+ if ((checkBlockHash == checkBlockHash))
457564 then {
458- let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
459- if ((checkChain == checkChain))
565+ let checkEpoch = ensureCorrectEpoch(epoch)
566+ if ((checkEpoch == checkEpoch))
460567 then {
461- let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
462- if ((checkReference == checkReference))
568+ let checkGenerator = ensureMiningEpoch(i.originCaller)
569+ if ((checkGenerator == checkGenerator))
463570 then {
464- let thisEpochMeta = match epochMeta(height) {
465- case _: Unit =>
466- StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
467- case other =>
468- throw("Epoch already started")
571+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
572+ if ((checkChain == checkChain))
573+ then {
574+ let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
575+ if ((checkReference == checkReference))
576+ then {
577+ let thisEpochMeta = match epochMeta(height) {
578+ case _: Unit =>
579+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
580+ case other =>
581+ throw("Epoch already started")
582+ }
583+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
584+ let newChainHeight = (mainChainHeight + 1)
585+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(mainChainLastBlock)) + i.originCaller.bytes)
586+ ([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(mainChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
587+ }
588+ else throw("Strict value is not equal to itself.")
589+ }
590+ else throw("Strict value is not equal to itself.")
469591 }
470- let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
471- let newChainHeight = (mainChainHeight + 1)
472- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(mainChainLastBlock)) + i.originCaller.bytes)
473- ([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(mainChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
592+ else throw("Strict value is not equal to itself.")
593+ }
594+ else throw("Strict value is not equal to itself.")
595+ }
596+ else throw("Strict value is not equal to itself.")
597+ }
598+ else throw("Strict value is not equal to itself.")
599+ }
600+
601+
602+
603+@Callable(i)
604+func extendMainChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
605+ let checkVersion = requireElToClTransfersEnabled()
606+ if ((checkVersion == checkVersion))
607+ then {
608+ let checkBlockHash = validateBlockHash(blockHashHex)
609+ if ((checkBlockHash == checkBlockHash))
610+ then {
611+ let checkEpoch = ensureCorrectEpoch(epoch)
612+ if ((checkEpoch == checkEpoch))
613+ then {
614+ let checkGenerator = ensureMiningEpoch(i.originCaller)
615+ if ((checkGenerator == checkGenerator))
616+ then {
617+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
618+ if ((checkChain == checkChain))
619+ then {
620+ let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
621+ if ((checkReference == checkReference))
622+ then {
623+ let thisEpochMeta = match epochMeta(height) {
624+ case _: Unit =>
625+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
626+ case other =>
627+ throw("Epoch already started")
628+ }
629+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
630+ let newChainHeight = (mainChainHeight + 1)
631+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex), StringEntry(chainMetaKey(mainChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
632+ }
633+ else throw("Strict value is not equal to itself.")
634+ }
635+ else throw("Strict value is not equal to itself.")
474636 }
475637 else throw("Strict value is not equal to itself.")
476638 }
485647
486648 @Callable(i)
487649 func startAltChain (blockHashHex,referenceHex,epoch) = {
488- let checkEpoch = ensureCorrectEpoch(epoch)
489- if ((checkEpoch == checkEpoch))
650+ let checkVersion = requireElToClTransfersDisabled()
651+ if ((checkVersion == checkVersion))
490652 then {
491- let checkGenerator = ensureMiningEpoch(i.originCaller)
492- if ((checkGenerator == checkGenerator))
653+ let checkBlockHash = validateBlockHash(blockHashHex)
654+ if ((checkBlockHash == checkBlockHash))
493655 then {
494- let $t01309313171 = blockMeta(referenceHex)
495- let refChainHeight = $t01309313171._1
496- let refEpoch = $t01309313171._2
497- let refRef = $t01309313171._3
498- let refGenerator = $t01309313171._4
499- let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
500- let epochRef = if ((refEpoch >= finalizedEpoch))
501- then refEpoch
502- else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
503- let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
504- if ((checkChain == checkChain))
656+ let checkEpoch = ensureCorrectEpoch(epoch)
657+ if ((checkEpoch == checkEpoch))
505658 then {
506- let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
507- let referenceHeight = blockMeta(referenceHex)._1
508- let newChainHeight = (referenceHeight + 1)
509- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
510- let thisEpochMeta = match epochMeta(height) {
511- case _: Unit =>
512- StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
513- case other =>
514- throw("Epoch already started")
659+ let checkGenerator = ensureMiningEpoch(i.originCaller)
660+ if ((checkGenerator == checkGenerator))
661+ then {
662+ let $t01969819802 = blockMeta(referenceHex)
663+ let refChainHeight = $t01969819802._1
664+ let refEpoch = $t01969819802._2
665+ let refRef = $t01969819802._3
666+ let refGenerator = $t01969819802._4
667+ let refIgnored1 = $t01969819802._5
668+ let refIgnored2 = $t01969819802._6
669+ let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
670+ let epochRef = if ((refEpoch >= finalizedEpoch))
671+ then refEpoch
672+ else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
673+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
674+ if ((checkChain == checkChain))
675+ then {
676+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
677+ let newChainHeight = (blockMeta(referenceHex)._1 + 1)
678+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
679+ let thisEpochMeta = match epochMeta(height) {
680+ case _: Unit =>
681+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
682+ case other =>
683+ throw("Epoch already started")
684+ }
685+[thisEpochMeta, BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), StringEntry(chainMetaKey(newChainId), ((toString(newChainHeight) + SEP) + 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)]
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
515690 }
516-[thisEpochMeta, BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), StringEntry(chainMetaKey(newChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), referenceHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
691+ else throw("Strict value is not equal to itself.")
692+ }
693+ else throw("Strict value is not equal to itself.")
694+ }
695+ else throw("Strict value is not equal to itself.")
696+ }
697+
698+
699+
700+@Callable(i)
701+func startAltChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
702+ let checkVersion = requireElToClTransfersEnabled()
703+ if ((checkVersion == checkVersion))
704+ then {
705+ let checkBlockHash = validateBlockHash(blockHashHex)
706+ if ((checkBlockHash == checkBlockHash))
707+ then {
708+ let checkEpoch = ensureCorrectEpoch(epoch)
709+ if ((checkEpoch == checkEpoch))
710+ then {
711+ let checkGenerator = ensureMiningEpoch(i.originCaller)
712+ if ((checkGenerator == checkGenerator))
713+ then {
714+ let $t02161221716 = blockMeta(referenceHex)
715+ let refChainHeight = $t02161221716._1
716+ let refEpoch = $t02161221716._2
717+ let refRef = $t02161221716._3
718+ let refGenerator = $t02161221716._4
719+ let refIgnored1 = $t02161221716._5
720+ let refIgnored2 = $t02161221716._6
721+ let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
722+ let epochRef = if ((refEpoch >= finalizedEpoch))
723+ then refEpoch
724+ else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
725+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
726+ if ((checkChain == checkChain))
727+ then {
728+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
729+ let newChainHeight = (blockMeta(referenceHex)._1 + 1)
730+ let thisEpochMeta = match epochMeta(height) {
731+ case _: Unit =>
732+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
733+ case other =>
734+ throw("Epoch already started")
735+ }
736+[thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), StringEntry(chainMetaKey(newChainId), ((toString(newChainHeight) + SEP) + 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)]
737+ }
738+ else throw("Strict value is not equal to itself.")
739+ }
740+ else throw("Strict value is not equal to itself.")
517741 }
518742 else throw("Strict value is not equal to itself.")
519743 }
526750
527751 @Callable(i)
528752 func extendAltChain (chainId,blockHashHex,referenceHex,epoch) = {
529- let checkEpoch = ensureCorrectEpoch(epoch)
530- if ((checkEpoch == checkEpoch))
753+ let checkVersion = requireElToClTransfersDisabled()
754+ if ((checkVersion == checkVersion))
531755 then {
532- let checkGenerator = ensureMiningEpoch(i.originCaller)
533- if ((checkGenerator == checkGenerator))
756+ let checkBlockHash = validateBlockHash(blockHashHex)
757+ if ((checkBlockHash == checkBlockHash))
534758 then {
535- let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._3))
536- if ((checkChain == checkChain))
759+ let checkEpoch = ensureCorrectEpoch(epoch)
760+ if ((checkEpoch == checkEpoch))
537761 then {
538- let $t01534015394 = chainMeta(chainId)
539- let chainHeight = $t01534015394._1
540- let chainLastBlock = $t01534015394._2
541- let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
542- if ((checkReference == checkReference))
762+ let checkGenerator = ensureMiningEpoch(i.originCaller)
763+ if ((checkGenerator == checkGenerator))
543764 then {
544- let newChainHeight = (chainHeight + 1)
545- let prevEpoch = blockMeta(referenceHex)._2
546- let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
765+ let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
766+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
767+ if ((checkChain == checkChain))
547768 then {
548- let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
549- ([IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (valueOrElse(getInteger(lastChainIdKey), 0) + 1))] ++ updateFinalizedBlock)
769+ let $t02395524009 = chainMeta(chainId)
770+ let chainHeight = $t02395524009._1
771+ let chainLastBlock = $t02395524009._2
772+ let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
773+ if ((checkReference == checkReference))
774+ then {
775+ let newChainHeight = (chainHeight + 1)
776+ let prevEpoch = blockMeta(referenceHex)._2
777+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
778+ then {
779+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
780+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
781+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
782+ }
783+ else nil
784+ let thisEpochMeta = match epochMeta(height) {
785+ case _: Unit =>
786+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
787+ case other =>
788+ throw("Epoch already started")
789+ }
790+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
791+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
792+ else false)
793+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
794+ else nil
795+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
796+ ((([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
797+ }
798+ else throw("Strict value is not equal to itself.")
550799 }
551- else nil
552- let thisEpochMeta = match epochMeta(height) {
553- case _: Unit =>
554- StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
555- case other =>
556- throw("Epoch already started")
800+ else throw("Strict value is not equal to itself.")
557801 }
558- let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
559- then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
560- else false)
561- then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._1)]
562- else nil
563- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
564- ((([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
802+ else throw("Strict value is not equal to itself.")
803+ }
804+ else throw("Strict value is not equal to itself.")
805+ }
806+ else throw("Strict value is not equal to itself.")
807+ }
808+ else throw("Strict value is not equal to itself.")
809+ }
810+
811+
812+
813+@Callable(i)
814+func extendAltChain_v2 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
815+ let checkVersion = requireElToClTransfersEnabled()
816+ if ((checkVersion == checkVersion))
817+ then {
818+ let checkBlockHash = validateBlockHash(blockHashHex)
819+ if ((checkBlockHash == checkBlockHash))
820+ then {
821+ let checkEpoch = ensureCorrectEpoch(epoch)
822+ if ((checkEpoch == checkEpoch))
823+ then {
824+ let checkGenerator = ensureMiningEpoch(i.originCaller)
825+ if ((checkGenerator == checkGenerator))
826+ then {
827+ let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
828+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
829+ if ((checkChain == checkChain))
830+ then {
831+ let $t02661226666 = chainMeta(chainId)
832+ let chainHeight = $t02661226666._1
833+ let chainLastBlock = $t02661226666._2
834+ let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
835+ if ((checkReference == checkReference))
836+ then {
837+ let newChainHeight = (chainHeight + 1)
838+ let prevEpoch = blockMeta(referenceHex)._2
839+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
840+ then {
841+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
842+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
843+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
844+ }
845+ else nil
846+ let thisEpochMeta = match epochMeta(height) {
847+ case _: Unit =>
848+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
849+ case other =>
850+ throw("Epoch already started")
851+ }
852+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
853+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
854+ else false)
855+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
856+ else nil
857+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
858+ }
859+ else throw("Strict value is not equal to itself.")
860+ }
861+ else throw("Strict value is not equal to itself.")
565862 }
566863 else throw("Strict value is not equal to itself.")
567864 }
671968
672969
673970 @Callable(i)
674-func setup (genesisBlockHashHex,minerReward,stakingContractAddressB58) = if (isContractSetup())
971+func withdraw (blockHashHex,merkleProof,transferIndexInBlock,amount) = {
972+ let checkActivation = requireElToClTransfersEnabled()
973+ if ((checkActivation == checkActivation))
974+ then {
975+ let withdrawBlockMeta = blockMeta(blockHashHex)
976+ let withdrawBlockHeight = withdrawBlockMeta._1
977+ let finalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
978+ let mainChainLastBlockHeight = blockMeta(mainChainLastBlock)._1
979+ if ((withdrawBlockHeight > finalizedBlockHeight))
980+ then throw(((("EL block #" + toString(withdrawBlockHeight)) + " is not finalized. The current finalized is #") + toString(finalizedBlockHeight)))
981+ else {
982+ let withdrawBlockChainId = withdrawBlockMeta._5
983+ let isMainChain = (withdrawBlockChainId == mainChainId)
984+ let relatesToMainChain = match getInteger(chainForkedHeightKey(withdrawBlockChainId)) {
985+ case forkedHeight: Int =>
986+ (forkedHeight > withdrawBlockHeight)
987+ case _ =>
988+ throw((((blockHashHex + " is on an alternative chain #") + toString(withdrawBlockChainId)) + " that was not approved by majority. Wait for some blocks"))
989+ }
990+ if (if (isMainChain)
991+ then true
992+ else relatesToMainChain)
993+ then {
994+ let recipient = i.originCaller
995+ let recipientPkHash = take(drop(recipient.bytes, 2), PUBLIC_KEY_HASH_SIZE)
996+ let zeroAmountBytes = base58'11111111111111111111111111111111111111111111'
997+ let amountBytes = toBytes(amount)
998+ let elEventData = ((recipientPkHash + take(zeroAmountBytes, (size(zeroAmountBytes) - size(amountBytes)))) + amountBytes)
999+ let elEventDataDigest = blake2b256_16Kb(elEventData)
1000+ let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock)
1001+ let expectedRootHash = withdrawBlockMeta._6
1002+ if ((calculatedRootHash == expectedRootHash))
1003+ then {
1004+ let tokenId = fromBase58String(getStringValue(tokenIdKey))
1005+ let transfersKey = blockElToClTransfersKey(blockHashHex)
1006+[Reissue(tokenId, amount, true), ScriptTransfer(recipient, amount, tokenId), StringEntry(transfersKey, setOrFail(valueOrElse(getString(transfersKey), ""), transferIndexInBlock))]
1007+ }
1008+ else throw(((((("Expected root hash: " + toBase16String(expectedRootHash)) + ", got: ") + toBase16String(calculatedRootHash)) + ". Event data digest: ") + toBase64String(elEventDataDigest)))
1009+ }
1010+ else throw((("Expected " + blockHashHex) + " to be either on the main chain or relate to it"))
1011+ }
1012+ }
1013+ else throw("Strict value is not equal to itself.")
1014+ }
1015+
1016+
1017+
1018+@Callable(i)
1019+func setup (genesisBlockHashHex,minerRewardInGwei,stakingContractAddressB58,elBridgeAddressHex) = if (isContractSetup())
6751020 then throw("The contract has been already set up")
1021+ else if ((0 > minerRewardInGwei))
1022+ then throw("The miner reward must be nonnegative")
1023+ else {
1024+ let genesisBlockHash = fromBase16String(genesisBlockHashHex)
1025+ let emptyPk = base58'11111111111111111111111111111111'
1026+ let genesisMinerAddress = addressFromPublicKey(emptyPk)
1027+ let genesisEthRewardAddress = base58'11111111111111111111'
1028+ let genesisBlockReferenceHash = "0000000000000000000000000000000000000000000000000000000000000000"
1029+ let issue = Issue("UNIT0", "Native token", 0, 8, true)
1030+ let tokenId = calculateAssetId(issue)
1031+[mkBlockMetaEntry(genesisBlockHashHex, 0, genesisBlockReferenceHash, genesisMinerAddress, mainChainId, ""), StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), StringEntry(chainMetaKey(0), ("0," + genesisBlockHashHex)), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(stakingContractAddressKey, stakingContractAddressB58), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), IntegerEntry(prevRandaoHeightKey, 0), IntegerEntry(elToClTransfersEpochKey, 0), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, ("0x" + elBridgeAddressHex))]
1032+ }
1033+
1034+
1035+
1036+@Callable(i)
1037+func setupElToClTransfers (activationHeight,elBridgeAddressHex) = if (isDefined(getInteger(elToClTransfersEpochKey)))
1038+ then throw("EL to CL transfers feature was set up")
6761039 else {
677- let genesisBlockHash = fromBase16String(genesisBlockHashHex)
678- let emptyPk = base58'11111111111111111111111111111111'
679- let genesisMinerAddress = addressFromPublicKey(emptyPk)
680- let genesisEthRewardAddress = base58'11111111111111111111'
681- let genesisBlockReferenceHash = base58'11111111111111111111111111111111'
682- let genesisBlockMeta = (((toBytes(0) + toBytes(height)) + genesisBlockReferenceHash) + genesisMinerAddress.bytes)
683-[BinaryEntry((blockMetaK + genesisBlockHashHex), genesisBlockMeta), StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), StringEntry(chainMetaKey(0), ("0," + genesisBlockHashHex)), IntegerEntry(minerRewardKey, minerReward), StringEntry(stakingContractAddressKey, stakingContractAddressB58), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex)]
1040+ let issue = Issue("UNIT0", "Native token", 0, 8, true)
1041+ let tokenId = calculateAssetId(issue)
1042+[IntegerEntry(elToClTransfersEpochKey, activationHeight), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, ("0x" + elBridgeAddressHex))]
6841043 }
6851044
6861045
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 8 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let INT_MAX = 9223372036854775807
55
66 let WAVES = 100000000
77
88 let MIN_BALANCE = (20000 * WAVES)
99
1010 let SEP = ","
1111
1212 let BLOCK_HASH_SIZE = 32
1313
1414 let ADDRESS_SIZE = 26
15+
16+let PUBLIC_KEY_HASH_SIZE = 20
17+
18+let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
1519
1620 let thisEpochDataKey = "thisEpochData"
1721
1822 let allMinersKey = "allMiners"
1923
2024 let mainChainIdKey = "mainChainId"
2125
2226 let lastChainIdKey = "lastChainId"
2327
2428 let firstValidAltChainIdKey = "firstValidAltChainId"
2529
2630 let minerRewardKey = "minerReward"
2731
2832 let stakingContractAddressKey = "stakingContractAddress"
2933
3034 let blockMetaK = "block_0x"
3135
3236 let finalizedBlockKey = "finalizedBlock"
37+
38+let tokenIdKey = "tokenId"
39+
40+let elBridgeAddressKey = "elBridgeAddress"
41+
42+let prevRandaoHeightKey = "prevRandaoHeight"
43+
44+let elToClTransfersEpochKey = "elToClTransfersEpoch"
3345
3446 func pad (i) = {
3547 let s = toString(i)
3648 match size(s) {
3749 case _ =>
3850 if ((1 == $match0))
3951 then ("0000000" + s)
4052 else if ((2 == $match0))
4153 then ("000000" + s)
4254 else if ((3 == $match0))
4355 then ("00000" + s)
4456 else if ((4 == $match0))
4557 then ("0000" + s)
4658 else if ((5 == $match0))
4759 then ("000" + s)
4860 else if ((6 == $match0))
4961 then ("00" + s)
5062 else if ((7 == $match0))
5163 then ("0" + s)
5264 else s
5365 }
5466 }
5567
5668
69+func blockElToClTransfersKey (blockHashHex) = ("elToClTransfers_0x" + blockHashHex)
70+
71+
5772 func epochMetaKey (epoch) = ("epoch_" + pad(epoch))
5873
5974
6075 func chainFirstBlockIdKey (chainId) = (("chain" + toString(chainId)) + "FirstBlock")
6176
6277
6378 func chainMetaKey (chainId) = ("chain_" + pad(chainId))
6479
6580
6681 func chainLastHeightKey (chainId,miner) = ((("chain_" + pad(chainId)) + "_") + toString(miner))
6782
6883
84+func chainForkedHeightKey (chainId) = (("chain_" + pad(chainId)) + "ForkedHeight")
85+
86+
6987 func supportersKey (chainId) = (("chain" + toString(chainId)) + "Supporters")
7088
7189
7290 func minerRewardAddressKey (minerAddr) = (("miner_" + minerAddr) + "_RewardAddress")
7391
7492
7593 func minerPkKey (rewardAddress) = (("miner_0x" + rewardAddress) + "_PK")
7694
7795
7896 func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId")
97+
98+
99+let elToClTransfersEpoch = valueOrElse(getInteger(this, elToClTransfersEpochKey), INT_MAX)
100+
101+func requireElToClTransfersDisabled () = if ((elToClTransfersEpoch > height))
102+ then unit
103+ else throw((("EL to CL transfers activated on epoch #" + toString(height)) + ". Upgrade your client"))
104+
105+
106+func requireElToClTransfersEnabled () = if ((height >= elToClTransfersEpoch))
107+ then unit
108+ else throw(((("EL to CL transfers haven't activated on epoch #" + toString(height)) + ". Wait for activation on #") + toString(elToClTransfersEpoch)))
79109
80110
81111 let stakingContractAddress = match getString(this, stakingContractAddressKey) {
82112 case s: String =>
83113 valueOrErrorMessage(addressFromString(s), ("invalid staking contract address: " + s))
84114 case _ =>
85115 Address(getBinaryValue(this, stakingContractAddressKey))
86116 }
87117
88118 func generatingBalance (address) = match getString(stakingContractAddress, ("%s__" + toString(address))) {
89119 case str: String =>
90120 let paramList = split(str, "__")
91121 let prevHeight = parseIntValue(paramList[1])
92122 let prevBalance = parseIntValue(paramList[2])
93123 let nextHeight = parseIntValue(paramList[3])
94124 let nextBalance = parseIntValue(paramList[4])
95125 if ((height >= nextHeight))
96126 then nextBalance
97127 else if ((height >= prevHeight))
98128 then prevBalance
99129 else 0
100130 case _ =>
101131 0
102132 }
103133
104134
105135 func chainMeta (chainId) = {
106136 let s = getStringValue(chainMetaKey(chainId))
107137 let items = split(s, SEP)
108138 $Tuple2(parseIntValue(items[0]), items[1])
109139 }
110140
111141
112142 let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0)
113143
114-let $t028292895 = chainMeta(mainChainId)
144+let $t049114977 = chainMeta(mainChainId)
115145
116-let mainChainHeight = $t028292895._1
146+let mainChainHeight = $t049114977._1
117147
118-let mainChainLastBlock = $t028292895._2
148+let mainChainLastBlock = $t049114977._2
119149
120150 func epochMeta (epoch) = match getString(epochMetaKey(epoch)) {
121151 case s: String =>
122152 let fragments = split(s, SEP)
123153 $Tuple3(addressFromStringValue(fragments[0]), parseIntValue(fragments[1]), fragments[2])
124154 case _ =>
125155 unit
126156 }
127157
128158
129-let $t031273591 = match epochMeta(height) {
159+let $t052085672 = match epochMeta(height) {
130160 case m: (Address, Int, String) =>
131161 m
132162 case _ =>
133163 match getString(thisEpochDataKey) {
134164 case rawThisEpochData: String =>
135165 let thisEpochData = split(rawThisEpochData, SEP)
136166 let thisEpoch = parseIntValue(thisEpochData[0])
137167 $Tuple3(if ((thisEpoch == height))
138168 then addressFromStringValue(thisEpochData[1])
139169 else unit, 0, "")
140170 case _ =>
141171 $Tuple3(unit, 0, "")
142172 }
143173 }
144174
145-let thisEpochMiner = $t031273591._1
175+let thisEpochMiner = $t052085672._1
146176
147-let thisEpochRef = $t031273591._2
177+let thisEpochRef = $t052085672._2
148178
149-let thisEpochLastBlock = $t031273591._3
179+let thisEpochLastBlock = $t052085672._3
150180
151181 let allMinersStr = valueOrElse(getString(allMinersKey), "")
152182
153183 let allMiners = match allMinersStr {
154184 case _ =>
155185 if (("" == $match0))
156186 then nil
157187 else if ($isInstanceOf($match0, "String"))
158188 then {
159189 let raw = $match0
160190 split_4C(raw, SEP)
161191 }
162192 else throw("Match error")
163193 }
164194
165195 func blockMeta (blockId) = {
166196 let meta = getBinaryValue((blockMetaK + blockId))
167197 let blockHeight = toInt(meta)
168198 let blockEpoch = toInt(meta, 8)
169199 let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE)
170- let blockGenerator = takeRight(meta, ADDRESS_SIZE)
171- $Tuple4(blockHeight, blockEpoch, blockParent, blockGenerator)
200+ let blockGenerator = take(drop(meta, (16 + BLOCK_HASH_SIZE)), ADDRESS_SIZE)
201+ if ((elToClTransfersEpoch > blockEpoch))
202+ then $Tuple6(blockHeight, blockEpoch, blockParent, blockGenerator, 0, base58'')
203+ else {
204+ let chainId = toInt(drop(meta, ((16 + BLOCK_HASH_SIZE) + ADDRESS_SIZE)))
205+ let elToClTransfersRootHash = drop(meta, ((24 + BLOCK_HASH_SIZE) + ADDRESS_SIZE))
206+ $Tuple6(blockHeight, blockEpoch, blockParent, blockGenerator, chainId, elToClTransfersRootHash)
207+ }
208+ }
209+
210+
211+func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,blockGenerator,chainId,elToClTransfersRootHashHex) = {
212+ let blockEpochBytes = toBytes(height)
213+ let blockMetaBytes = (((((toBytes(blockHeight) + blockEpochBytes) + fromBase16String(blockParentHex)) + blockGenerator.bytes) + toBytes(chainId)) + fromBase16String(elToClTransfersRootHashHex))
214+ BinaryEntry((blockMetaK + blockHashHex), blockMetaBytes)
172215 }
173216
174217
175218 func lastHeightBy (miner,chainId) = match getInteger(chainLastHeightKey(chainId, miner)) {
176219 case h: Int =>
177220 h
178221 case _ =>
179222 let blockHash = getStringValue(((("chain" + toString(chainId)) + "LastMinedBy") + toString(miner)))
180223 blockMeta(blockHash)._1
181224 }
182225
183226
184-let $t043515317 = {
227+let $t073208286 = {
185228 let hitSource = match lastBlock.vrf {
186229 case vrf: ByteVector =>
187230 vrf
188231 case _ =>
189232 lastBlock.generationSignature
190233 }
191234 func processMiner (prev,miner) = {
192- let $t046494712 = prev
193- let prevDelay = $t046494712._1
194- let prevMiner = $t046494712._2
195- let prevTotalBalance = $t046494712._3
196- let prevMiners = $t046494712._4
235+ let $t076187681 = prev
236+ let prevDelay = $t076187681._1
237+ let prevMiner = $t076187681._2
238+ let prevTotalBalance = $t076187681._3
239+ let prevMiners = $t076187681._4
197240 let minerAddress = addressFromStringValue(miner)
198241 let wavesGenBalance = wavesBalance(minerAddress).generating
199242 let minerBalance = generatingBalance(minerAddress)
200243 if (if ((MIN_BALANCE > wavesGenBalance))
201244 then true
202245 else (0 >= minerBalance))
203246 then prev
204247 else {
205248 let nextDelay = calculateDelay(minerAddress, minerBalance)
206249 if ((prevDelay > nextDelay))
207250 then $Tuple4(nextDelay, miner, (prevTotalBalance + minerBalance), (prevMiners :+ miner))
208251 else $Tuple4(prevDelay, prevMiner, (prevTotalBalance + minerBalance), (prevMiners :+ miner))
209252 }
210253 }
211254
212255 let $l = allMiners
213256 let $s = size($l)
214257 let $acc0 = $Tuple4(INT_MAX, "", 0, nil)
215258 func $f0_1 ($a,$i) = if (($i >= $s))
216259 then $a
217260 else processMiner($a, $l[$i])
218261
219262 func $f0_2 ($a,$i) = if (($i >= $s))
220263 then $a
221264 else throw("List size exceeds 50")
222265
223266 $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)
224267 }
225268
226-let computedDelay = $t043515317._1
269+let computedDelay = $t073208286._1
227270
228-let computedGenerator = $t043515317._2
271+let computedGenerator = $t073208286._2
229272
230-let computedTotalBalance = $t043515317._3
273+let computedTotalBalance = $t073208286._3
231274
232-let filteredMiners = $t043515317._4
275+let filteredMiners = $t073208286._4
233276
234277 func getChainLastBlockId (chainId) = chainMeta(chainId)._2
235278
236279
237-let $t053835485 = blockMeta(mainChainLastBlock)
280+let $t083528487 = blockMeta(mainChainLastBlock)
238281
239-let ignored = $t053835485._1
282+let mclbIgnored1 = $t083528487._1
240283
241-let mainChainEpoch = $t053835485._2
284+let mainChainEpoch = $t083528487._2
242285
243-let mainChainParentHash = $t053835485._3
286+let mainChainParentHash = $t083528487._3
244287
245-let mainChainGenerator = $t053835485._4
288+let mainChainGenerator = $t083528487._4
289+
290+let mclbIgnored2 = $t083528487._5
291+
292+let mclbIgnored3 = $t083528487._6
246293
247294 func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = {
248295 let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "")
249296 let halfBalance = (computedTotalBalance / 2)
250297 func step (prev,next) = {
251- let $t058515915 = prev
252- let thisEpoch = $t058515915._1
253- let totalBalance = $t058515915._2
254- let maybeSafeEpoch = $t058515915._3
255- let prevMiners = $t058515915._4
298+ let $t088538917 = prev
299+ let thisEpoch = $t088538917._1
300+ let totalBalance = $t088538917._2
301+ let maybeSafeEpoch = $t088538917._3
302+ let prevMiners = $t088538917._4
256303 match maybeSafeEpoch {
257304 case _: Unit =>
258- let $t059736139 = if ((thisEpoch == height))
305+ let $t089759141 = if ((thisEpoch == height))
259306 then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash)
260307 else value(epochMeta(thisEpoch))
261- let miner = $t059736139._1
262- let prevEpoch = $t059736139._2
263- let lastBlockHash = $t059736139._3
308+ let miner = $t089759141._1
309+ let prevEpoch = $t089759141._2
310+ let lastBlockHash = $t089759141._3
264311 if ((prevEpoch == 0))
265312 then $Tuple4(thisEpoch, totalBalance, lastBlockHash, allMiners)
266313 else {
267- let $t062646466 = if (containsElement(prevMiners, miner))
314+ let $t092669468 = if (containsElement(prevMiners, miner))
268315 then $Tuple2(totalBalance, prevMiners)
269316 else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners)
270- let newTotalBalance = $t062646466._1
271- let newMiners = $t062646466._2
317+ let newTotalBalance = $t092669468._1
318+ let newMiners = $t092669468._2
272319 if ((newTotalBalance > halfBalance))
273320 then $Tuple4(thisEpoch, newTotalBalance, lastBlockHash, allMiners)
274321 else $Tuple4(prevEpoch, newTotalBalance, unit, newMiners)
275322 }
276323 case _ =>
277324 prev
278325 }
279326 }
280327
281- let $t067016834 = {
328+ let $t097019834 = {
282329 let $l = (offsets_100 ++ offsets_100)
283330 let $s = size($l)
284331 let $acc0 = $Tuple4(height, 0, unit, nil)
285332 func $f0_1 ($a,$i) = if (($i >= $s))
286333 then $a
287334 else step($a, $l[$i])
288335
289336 func $f0_2 ($a,$i) = if (($i >= $s))
290337 then $a
291338 else throw("List size exceeds 200")
292339
293340 $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($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 101), 102), 103), 104), 105), 106), 107), 108), 109), 110), 111), 112), 113), 114), 115), 116), 117), 118), 119), 120), 121), 122), 123), 124), 125), 126), 127), 128), 129), 130), 131), 132), 133), 134), 135), 136), 137), 138), 139), 140), 141), 142), 143), 144), 145), 146), 147), 148), 149), 150), 151), 152), 153), 154), 155), 156), 157), 158), 159), 160), 161), 162), 163), 164), 165), 166), 167), 168), 169), 170), 171), 172), 173), 174), 175), 176), 177), 178), 179), 180), 181), 182), 183), 184), 185), 186), 187), 188), 189), 190), 191), 192), 193), 194), 195), 196), 197), 198), 199), 200)
294341 }
295- let fallbackEpoch = $t067016834._1
296- let totalBalance = $t067016834._2
297- let finalizedBlockHashOpt = $t067016834._3
298- let miners = $t067016834._4
342+ let fallbackEpoch = $t097019834._1
343+ let totalBalance = $t097019834._2
344+ let finalizedBlockHashOpt = $t097019834._3
345+ let miners = $t097019834._4
299346 match finalizedBlockHashOpt {
300347 case finalizedBlockHash: String =>
301348 finalizedBlockHash
302349 case _ =>
303350 value(epochMeta(fallbackEpoch))._3
304351 }
305352 }
306353
307354
308355 func supportingBalance (chainId) = {
309356 func addBalance (acc,generatorStr) = {
310- let $t071047140 = acc
311- let totalBalance = $t071047140._1
312- let generators = $t071047140._2
357+ let $t01010410140 = acc
358+ let totalBalance = $t01010410140._1
359+ let generators = $t01010410140._2
313360 let generator = addressFromStringValue(generatorStr)
314361 if (containsElement(generators, generator))
315362 then acc
316363 else {
317364 let balance = generatingBalance(generator)
318365 $Tuple2((totalBalance + balance), (generators :+ generator))
319366 }
320367 }
321368
322369 let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP)
323- let $t074627527 = {
370+ let $t01046210527 = {
324371 let $l = allGenerators
325372 let $s = size($l)
326373 let $acc0 = $Tuple2(0, nil)
327374 func $f0_1 ($a,$i) = if (($i >= $s))
328375 then $a
329376 else addBalance($a, $l[$i])
330377
331378 func $f0_2 ($a,$i) = if (($i >= $s))
332379 then $a
333380 else throw("List size exceeds 100")
334381
335382 $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)
336383 }
337- let balance = $t074627527._1
338- let _g = $t074627527._2
384+ let balance = $t01046210527._1
385+ let _g = $t01046210527._2
339386 balance
340387 }
341388
342389
343390 func isContractSetup () = isDefined(getInteger(minerRewardKey))
344391
345392
346393 func ensureMiningEpoch (generator) = if ((toString(generator) != computedGenerator))
347394 then throw(((((toBase58String(generator.bytes) + " is not allowed to mine in ") + toString(height)) + " epoch. Expected ") + computedGenerator))
348395 else unit
349396
350397
351398 func isReferenceCorrect (reference,lastBlock) = if ((reference == lastBlock))
352399 then unit
353400 else throw(((("Expected a reference to the chain last block: 0x" + lastBlock) + ". Got: 0x") + reference))
354401
355402
356403 func chainIsInactive (chainId) = {
357404 let firstBlockId = getStringValue(chainFirstBlockIdKey(chainId))
358405 let firstValidAltChainId = valueOrElse(getInteger(firstValidAltChainIdKey), 0)
359406 if ((firstValidAltChainId > chainId))
360407 then true
361408 else (blockMeta(getStringValue(finalizedBlockKey))._1 > blockMeta(firstBlockId)._1)
362409 }
363410
364411
365412 func minerChainId (miner) = valueOrElse(getInteger(minerChainIdKey(miner)), getInteger(("chainIdOf" + toString(miner))))
366413
367414
368415 func ensureExpectedOrInactiveChain (generator,expectedChainId,checkHeightBlock) = {
369416 let heightIsCorrect = match checkHeightBlock {
370417 case blockHash: String =>
371418 let lastMinedBlockHeight = lastHeightBy(generator, mainChainId)
372419 ((blockMeta(blockHash)._1 + 1) > lastMinedBlockHeight)
373420 case _ =>
374421 true
375422 }
376423 match minerChainId(generator) {
377424 case currentId: Int =>
378425 if (if ((currentId == expectedChainId))
379426 then true
380427 else if (chainIsInactive(currentId))
381428 then heightIsCorrect
382429 else false)
383430 then unit
384431 else throw(("miner is mining other chain " + toString(currentId)))
385432 case _ =>
386433 unit
387434 }
388435 }
389436
390437
391438 func ensureCorrectEpoch (epoch) = if ((epoch == height))
392439 then unit
393440 else throw(((("Expected block from epoch " + toString(height)) + ". Got ") + toString(epoch)))
394441
395442
396443 func addSupporter (chainId,generator) = {
397444 let supportersStr = getStringValue(supportersKey(chainId))
398445 let supporters = split_4C(supportersStr, SEP)
399446 if (containsElement(supporters, toString(generator)))
400447 then nil
401448 else [StringEntry(supportersKey(chainId), ((supportersStr + SEP) + toString(generator)))]
402449 }
403450
404451
452+func setOrFail (flags,index) = if ((0 > index))
453+ then throw(("Can't withdraw at negative index: " + toString(index)))
454+ else {
455+ let flagsSize = size(flags)
456+ if ((index >= flagsSize))
457+ then {
458+ let addZeroes = (index - flagsSize)
459+ if ((addZeroes > size(zeroesStr)))
460+ then throw((("Can't add " + toString(addZeroes)) + " empty flags. Contact with developers"))
461+ else ((flags + take(zeroesStr, addZeroes)) + "1")
462+ }
463+ else {
464+ let tail = drop(flags, index)
465+ let atIndex = take(tail, 1)
466+ if ((atIndex == "0"))
467+ then ((take(flags, index) + "1") + drop(tail, 1))
468+ else throw((("Transfer #" + toString(index)) + " has been already taken"))
469+ }
470+ }
471+
472+
405473 func validateBlockHash (hexStr) = {
406474 let decodedBytes = fromBase16String(hexStr)
407475 if ((size(decodedBytes) != 32))
408476 then throw("invalid block id length")
409477 else hexStr
410478 }
411479
412480
413481 func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = {
414482 let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
415483 let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex)
416- if ((newFinalizedBlockHash == newBlockHashHex))
484+ if (if ((newFinalizedBlockHash == newBlockHashHex))
485+ then true
486+ else (blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight))
417487 then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)]
418- else if ((blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight))
419- then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)]
420- else nil
488+ else nil
421489 }
422490
423491
424492 @Callable(i)
425-func appendBlock (blockHashHex,referenceHex) = if ((thisEpochMiner != i.originCaller))
426- then match thisEpochMiner {
427- case epochMiner: Address =>
428- throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
429- case _ =>
430- throw("not allowed to forge blocks in this epoch, epoch miner is absent")
493+func appendBlock (blockHashHex,referenceHex) = {
494+ let checkVersion = requireElToClTransfersDisabled()
495+ if ((checkVersion == checkVersion))
496+ then if ((thisEpochMiner != i.originCaller))
497+ then match thisEpochMiner {
498+ case epochMiner: Address =>
499+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
500+ case _ =>
501+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
502+ }
503+ else {
504+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
505+ let $t01464414695 = chainMeta(chainId)
506+ let chainHeight = $t01464414695._1
507+ let lastBlockId = $t01464414695._2
508+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
509+ if ((checkReference == checkReference))
510+ then {
511+ let newChainHeight = (chainHeight + 1)
512+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes)
513+ let checkBlockHash = validateBlockHash(blockHashHex)
514+ if ((checkBlockHash == checkBlockHash))
515+ then [BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
516+ else throw("Strict value is not equal to itself.")
517+ }
518+ else throw("Strict value is not equal to itself.")
519+ }
520+ else throw("Strict value is not equal to itself.")
431521 }
432- else {
433- let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
434- let $t01083310884 = chainMeta(chainId)
435- let chainHeight = $t01083310884._1
436- let lastBlockId = $t01083310884._2
437- let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
438- if ((checkReference == checkReference))
439- then {
440- let newChainHeight = (chainHeight + 1)
441- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes)
442- let blockHash = validateBlockHash(blockHashHex)
443-[BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
522+
523+
524+
525+@Callable(i)
526+func appendBlock_v2 (blockHashHex,referenceHex,elToClTransfersRootHashHex) = {
527+ let checkVersion = requireElToClTransfersEnabled()
528+ if ((checkVersion == checkVersion))
529+ then if ((thisEpochMiner != i.originCaller))
530+ then match thisEpochMiner {
531+ case epochMiner: Address =>
532+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
533+ case _ =>
534+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
535+ }
536+ else {
537+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
538+ let $t01596916020 = chainMeta(chainId)
539+ let chainHeight = $t01596916020._1
540+ let lastBlockId = $t01596916020._2
541+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
542+ if ((checkReference == checkReference))
543+ then {
544+ let newChainHeight = (chainHeight + 1)
545+ let checkBlockHash = validateBlockHash(blockHashHex)
546+ if ((checkBlockHash == checkBlockHash))
547+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
548+ else throw("Strict value is not equal to itself.")
549+ }
550+ else throw("Strict value is not equal to itself.")
444551 }
445- else throw("Strict value is not equal to itself.")
446- }
552+ else throw("Strict value is not equal to itself.")
553+ }
447554
448555
449556
450557 @Callable(i)
451558 func extendMainChain (blockHashHex,referenceHex,epoch) = {
452- let checkEpoch = ensureCorrectEpoch(epoch)
453- if ((checkEpoch == checkEpoch))
559+ let checkVersion = requireElToClTransfersDisabled()
560+ if ((checkVersion == checkVersion))
454561 then {
455- let checkGenerator = ensureMiningEpoch(i.originCaller)
456- if ((checkGenerator == checkGenerator))
562+ let checkBlockHash = validateBlockHash(blockHashHex)
563+ if ((checkBlockHash == checkBlockHash))
457564 then {
458- let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
459- if ((checkChain == checkChain))
565+ let checkEpoch = ensureCorrectEpoch(epoch)
566+ if ((checkEpoch == checkEpoch))
460567 then {
461- let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
462- if ((checkReference == checkReference))
568+ let checkGenerator = ensureMiningEpoch(i.originCaller)
569+ if ((checkGenerator == checkGenerator))
463570 then {
464- let thisEpochMeta = match epochMeta(height) {
465- case _: Unit =>
466- StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
467- case other =>
468- throw("Epoch already started")
571+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
572+ if ((checkChain == checkChain))
573+ then {
574+ let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
575+ if ((checkReference == checkReference))
576+ then {
577+ let thisEpochMeta = match epochMeta(height) {
578+ case _: Unit =>
579+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
580+ case other =>
581+ throw("Epoch already started")
582+ }
583+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
584+ let newChainHeight = (mainChainHeight + 1)
585+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(mainChainLastBlock)) + i.originCaller.bytes)
586+ ([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(mainChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
587+ }
588+ else throw("Strict value is not equal to itself.")
589+ }
590+ else throw("Strict value is not equal to itself.")
469591 }
470- let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
471- let newChainHeight = (mainChainHeight + 1)
472- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(mainChainLastBlock)) + i.originCaller.bytes)
473- ([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(mainChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
592+ else throw("Strict value is not equal to itself.")
593+ }
594+ else throw("Strict value is not equal to itself.")
595+ }
596+ else throw("Strict value is not equal to itself.")
597+ }
598+ else throw("Strict value is not equal to itself.")
599+ }
600+
601+
602+
603+@Callable(i)
604+func extendMainChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
605+ let checkVersion = requireElToClTransfersEnabled()
606+ if ((checkVersion == checkVersion))
607+ then {
608+ let checkBlockHash = validateBlockHash(blockHashHex)
609+ if ((checkBlockHash == checkBlockHash))
610+ then {
611+ let checkEpoch = ensureCorrectEpoch(epoch)
612+ if ((checkEpoch == checkEpoch))
613+ then {
614+ let checkGenerator = ensureMiningEpoch(i.originCaller)
615+ if ((checkGenerator == checkGenerator))
616+ then {
617+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
618+ if ((checkChain == checkChain))
619+ then {
620+ let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
621+ if ((checkReference == checkReference))
622+ then {
623+ let thisEpochMeta = match epochMeta(height) {
624+ case _: Unit =>
625+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
626+ case other =>
627+ throw("Epoch already started")
628+ }
629+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
630+ let newChainHeight = (mainChainHeight + 1)
631+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex), StringEntry(chainMetaKey(mainChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
632+ }
633+ else throw("Strict value is not equal to itself.")
634+ }
635+ else throw("Strict value is not equal to itself.")
474636 }
475637 else throw("Strict value is not equal to itself.")
476638 }
477639 else throw("Strict value is not equal to itself.")
478640 }
479641 else throw("Strict value is not equal to itself.")
480642 }
481643 else throw("Strict value is not equal to itself.")
482644 }
483645
484646
485647
486648 @Callable(i)
487649 func startAltChain (blockHashHex,referenceHex,epoch) = {
488- let checkEpoch = ensureCorrectEpoch(epoch)
489- if ((checkEpoch == checkEpoch))
650+ let checkVersion = requireElToClTransfersDisabled()
651+ if ((checkVersion == checkVersion))
490652 then {
491- let checkGenerator = ensureMiningEpoch(i.originCaller)
492- if ((checkGenerator == checkGenerator))
653+ let checkBlockHash = validateBlockHash(blockHashHex)
654+ if ((checkBlockHash == checkBlockHash))
493655 then {
494- let $t01309313171 = blockMeta(referenceHex)
495- let refChainHeight = $t01309313171._1
496- let refEpoch = $t01309313171._2
497- let refRef = $t01309313171._3
498- let refGenerator = $t01309313171._4
499- let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
500- let epochRef = if ((refEpoch >= finalizedEpoch))
501- then refEpoch
502- else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
503- let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
504- if ((checkChain == checkChain))
656+ let checkEpoch = ensureCorrectEpoch(epoch)
657+ if ((checkEpoch == checkEpoch))
505658 then {
506- let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
507- let referenceHeight = blockMeta(referenceHex)._1
508- let newChainHeight = (referenceHeight + 1)
509- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
510- let thisEpochMeta = match epochMeta(height) {
511- case _: Unit =>
512- StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
513- case other =>
514- throw("Epoch already started")
659+ let checkGenerator = ensureMiningEpoch(i.originCaller)
660+ if ((checkGenerator == checkGenerator))
661+ then {
662+ let $t01969819802 = blockMeta(referenceHex)
663+ let refChainHeight = $t01969819802._1
664+ let refEpoch = $t01969819802._2
665+ let refRef = $t01969819802._3
666+ let refGenerator = $t01969819802._4
667+ let refIgnored1 = $t01969819802._5
668+ let refIgnored2 = $t01969819802._6
669+ let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
670+ let epochRef = if ((refEpoch >= finalizedEpoch))
671+ then refEpoch
672+ else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
673+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
674+ if ((checkChain == checkChain))
675+ then {
676+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
677+ let newChainHeight = (blockMeta(referenceHex)._1 + 1)
678+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
679+ let thisEpochMeta = match epochMeta(height) {
680+ case _: Unit =>
681+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
682+ case other =>
683+ throw("Epoch already started")
684+ }
685+[thisEpochMeta, BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), StringEntry(chainMetaKey(newChainId), ((toString(newChainHeight) + SEP) + 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)]
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
515690 }
516-[thisEpochMeta, BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), StringEntry(chainMetaKey(newChainId), ((toString(newChainHeight) + SEP) + blockHashHex)), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), referenceHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
691+ else throw("Strict value is not equal to itself.")
692+ }
693+ else throw("Strict value is not equal to itself.")
694+ }
695+ else throw("Strict value is not equal to itself.")
696+ }
697+
698+
699+
700+@Callable(i)
701+func startAltChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
702+ let checkVersion = requireElToClTransfersEnabled()
703+ if ((checkVersion == checkVersion))
704+ then {
705+ let checkBlockHash = validateBlockHash(blockHashHex)
706+ if ((checkBlockHash == checkBlockHash))
707+ then {
708+ let checkEpoch = ensureCorrectEpoch(epoch)
709+ if ((checkEpoch == checkEpoch))
710+ then {
711+ let checkGenerator = ensureMiningEpoch(i.originCaller)
712+ if ((checkGenerator == checkGenerator))
713+ then {
714+ let $t02161221716 = blockMeta(referenceHex)
715+ let refChainHeight = $t02161221716._1
716+ let refEpoch = $t02161221716._2
717+ let refRef = $t02161221716._3
718+ let refGenerator = $t02161221716._4
719+ let refIgnored1 = $t02161221716._5
720+ let refIgnored2 = $t02161221716._6
721+ let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
722+ let epochRef = if ((refEpoch >= finalizedEpoch))
723+ then refEpoch
724+ else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
725+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
726+ if ((checkChain == checkChain))
727+ then {
728+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
729+ let newChainHeight = (blockMeta(referenceHex)._1 + 1)
730+ let thisEpochMeta = match epochMeta(height) {
731+ case _: Unit =>
732+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
733+ case other =>
734+ throw("Epoch already started")
735+ }
736+[thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), StringEntry(chainMetaKey(newChainId), ((toString(newChainHeight) + SEP) + 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)]
737+ }
738+ else throw("Strict value is not equal to itself.")
739+ }
740+ else throw("Strict value is not equal to itself.")
517741 }
518742 else throw("Strict value is not equal to itself.")
519743 }
520744 else throw("Strict value is not equal to itself.")
521745 }
522746 else throw("Strict value is not equal to itself.")
523747 }
524748
525749
526750
527751 @Callable(i)
528752 func extendAltChain (chainId,blockHashHex,referenceHex,epoch) = {
529- let checkEpoch = ensureCorrectEpoch(epoch)
530- if ((checkEpoch == checkEpoch))
753+ let checkVersion = requireElToClTransfersDisabled()
754+ if ((checkVersion == checkVersion))
531755 then {
532- let checkGenerator = ensureMiningEpoch(i.originCaller)
533- if ((checkGenerator == checkGenerator))
756+ let checkBlockHash = validateBlockHash(blockHashHex)
757+ if ((checkBlockHash == checkBlockHash))
534758 then {
535- let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._3))
536- if ((checkChain == checkChain))
759+ let checkEpoch = ensureCorrectEpoch(epoch)
760+ if ((checkEpoch == checkEpoch))
537761 then {
538- let $t01534015394 = chainMeta(chainId)
539- let chainHeight = $t01534015394._1
540- let chainLastBlock = $t01534015394._2
541- let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
542- if ((checkReference == checkReference))
762+ let checkGenerator = ensureMiningEpoch(i.originCaller)
763+ if ((checkGenerator == checkGenerator))
543764 then {
544- let newChainHeight = (chainHeight + 1)
545- let prevEpoch = blockMeta(referenceHex)._2
546- let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
765+ let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
766+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
767+ if ((checkChain == checkChain))
547768 then {
548- let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
549- ([IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (valueOrElse(getInteger(lastChainIdKey), 0) + 1))] ++ updateFinalizedBlock)
769+ let $t02395524009 = chainMeta(chainId)
770+ let chainHeight = $t02395524009._1
771+ let chainLastBlock = $t02395524009._2
772+ let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
773+ if ((checkReference == checkReference))
774+ then {
775+ let newChainHeight = (chainHeight + 1)
776+ let prevEpoch = blockMeta(referenceHex)._2
777+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
778+ then {
779+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
780+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
781+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
782+ }
783+ else nil
784+ let thisEpochMeta = match epochMeta(height) {
785+ case _: Unit =>
786+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
787+ case other =>
788+ throw("Epoch already started")
789+ }
790+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
791+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
792+ else false)
793+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
794+ else nil
795+ let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
796+ ((([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
797+ }
798+ else throw("Strict value is not equal to itself.")
550799 }
551- else nil
552- let thisEpochMeta = match epochMeta(height) {
553- case _: Unit =>
554- StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
555- case other =>
556- throw("Epoch already started")
800+ else throw("Strict value is not equal to itself.")
557801 }
558- let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
559- then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
560- else false)
561- then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._1)]
562- else nil
563- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
564- ((([BinaryEntry((blockMetaK + blockHashHex), newBlockMeta), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
802+ else throw("Strict value is not equal to itself.")
803+ }
804+ else throw("Strict value is not equal to itself.")
805+ }
806+ else throw("Strict value is not equal to itself.")
807+ }
808+ else throw("Strict value is not equal to itself.")
809+ }
810+
811+
812+
813+@Callable(i)
814+func extendAltChain_v2 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
815+ let checkVersion = requireElToClTransfersEnabled()
816+ if ((checkVersion == checkVersion))
817+ then {
818+ let checkBlockHash = validateBlockHash(blockHashHex)
819+ if ((checkBlockHash == checkBlockHash))
820+ then {
821+ let checkEpoch = ensureCorrectEpoch(epoch)
822+ if ((checkEpoch == checkEpoch))
823+ then {
824+ let checkGenerator = ensureMiningEpoch(i.originCaller)
825+ if ((checkGenerator == checkGenerator))
826+ then {
827+ let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
828+ let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
829+ if ((checkChain == checkChain))
830+ then {
831+ let $t02661226666 = chainMeta(chainId)
832+ let chainHeight = $t02661226666._1
833+ let chainLastBlock = $t02661226666._2
834+ let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
835+ if ((checkReference == checkReference))
836+ then {
837+ let newChainHeight = (chainHeight + 1)
838+ let prevEpoch = blockMeta(referenceHex)._2
839+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
840+ then {
841+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
842+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
843+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
844+ }
845+ else nil
846+ let thisEpochMeta = match epochMeta(height) {
847+ case _: Unit =>
848+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
849+ case other =>
850+ throw("Epoch already started")
851+ }
852+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
853+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
854+ else false)
855+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
856+ else nil
857+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex), StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex)), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
858+ }
859+ else throw("Strict value is not equal to itself.")
860+ }
861+ else throw("Strict value is not equal to itself.")
565862 }
566863 else throw("Strict value is not equal to itself.")
567864 }
568865 else throw("Strict value is not equal to itself.")
569866 }
570867 else throw("Strict value is not equal to itself.")
571868 }
572869 else throw("Strict value is not equal to itself.")
573870 }
574871
575872
576873
577874 @Callable(i)
578875 func join (rewardAddress) = {
579876 func checkRewardAddress (address) = match getBinary(minerPkKey(address)) {
580877 case pk: ByteVector =>
581878 if ((pk == i.originCallerPublicKey))
582879 then unit
583880 else throw(((("L2 miner address " + address) + " is already linked with ") + toBase58String(pk)))
584881 case _ =>
585882 unit
586883 }
587884
588885 if (!(isContractSetup()))
589886 then throw("The contract has not yet set up")
590887 else if ((MIN_BALANCE > wavesBalance(i.originCaller).generating))
591888 then throw(((("Insufficient generating balance: " + toString(wavesBalance(i.originCaller).generating)) + ". Required: ") + toString(MIN_BALANCE)))
592889 else if ((size(rewardAddress) != 20))
593890 then throw("rewardAddress should be an L2 address")
594891 else if ((size(allMiners) >= 50))
595892 then throw("too many miners")
596893 else {
597894 func checkExistence (exists,miner) = if (exists)
598895 then true
599896 else (miner == toString(i.originCaller))
600897
601898 let alreadyExists = {
602899 let $l = allMiners
603900 let $s = size($l)
604901 let $acc0 = false
605902 func $f0_1 ($a,$i) = if (($i >= $s))
606903 then $a
607904 else checkExistence($a, $l[$i])
608905
609906 func $f0_2 ($a,$i) = if (($i >= $s))
610907 then $a
611908 else throw("List size exceeds 50")
612909
613910 $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)
614911 }
615912 if (alreadyExists)
616913 then nil
617914 else {
618915 let newMiner = toString(i.originCaller)
619916 let rewardAddressHex = toBase16String(rewardAddress)
620917 let check = checkRewardAddress(rewardAddressHex)
621918 if ((check == check))
622919 then {
623920 let newMiners = if ((size(allMiners) == 0))
624921 then newMiner
625922 else ((allMinersStr + SEP) + newMiner)
626923 let deleteOldRewardAddressPk = match getString(minerRewardAddressKey(newMiner)) {
627924 case oldAddress: String =>
628925 if ((oldAddress == toBase16String(rewardAddress)))
629926 then nil
630927 else [DeleteEntry(minerPkKey(oldAddress))]
631928 case _ =>
632929 nil
633930 }
634931 ([StringEntry(allMinersKey, newMiners), StringEntry(minerRewardAddressKey(newMiner), ("0x" + rewardAddressHex)), BinaryEntry(minerPkKey(rewardAddressHex), i.originCallerPublicKey)] ++ deleteOldRewardAddressPk)
635932 }
636933 else throw("Strict value is not equal to itself.")
637934 }
638935 }
639936 }
640937
641938
642939
643940 @Callable(i)
644941 func leave () = {
645942 let leavingMiner = toString(i.originCaller)
646943 func skipLeavingMiner (acc,miner) = if ((miner == leavingMiner))
647944 then acc
648945 else (acc :+ miner)
649946
650947 let remainingMiners = {
651948 let $l = allMiners
652949 let $s = size($l)
653950 let $acc0 = nil
654951 func $f0_1 ($a,$i) = if (($i >= $s))
655952 then $a
656953 else skipLeavingMiner($a, $l[$i])
657954
658955 func $f0_2 ($a,$i) = if (($i >= $s))
659956 then $a
660957 else throw("List size exceeds 50")
661958
662959 $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)
663960 }
664961 let rewardAddrKey = minerRewardAddressKey(leavingMiner)
665962 let prevRewardAddress = valueOrErrorMessage(getString(this, rewardAddrKey), "miner has never joined")
666963 if ((thisEpochMiner == i.originCaller))
667964 then throw("designated miner can't leave")
668965 else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP)), DeleteEntry(rewardAddrKey), DeleteEntry(minerPkKey(prevRewardAddress))]
669966 }
670967
671968
672969
673970 @Callable(i)
674-func setup (genesisBlockHashHex,minerReward,stakingContractAddressB58) = if (isContractSetup())
971+func withdraw (blockHashHex,merkleProof,transferIndexInBlock,amount) = {
972+ let checkActivation = requireElToClTransfersEnabled()
973+ if ((checkActivation == checkActivation))
974+ then {
975+ let withdrawBlockMeta = blockMeta(blockHashHex)
976+ let withdrawBlockHeight = withdrawBlockMeta._1
977+ let finalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
978+ let mainChainLastBlockHeight = blockMeta(mainChainLastBlock)._1
979+ if ((withdrawBlockHeight > finalizedBlockHeight))
980+ then throw(((("EL block #" + toString(withdrawBlockHeight)) + " is not finalized. The current finalized is #") + toString(finalizedBlockHeight)))
981+ else {
982+ let withdrawBlockChainId = withdrawBlockMeta._5
983+ let isMainChain = (withdrawBlockChainId == mainChainId)
984+ let relatesToMainChain = match getInteger(chainForkedHeightKey(withdrawBlockChainId)) {
985+ case forkedHeight: Int =>
986+ (forkedHeight > withdrawBlockHeight)
987+ case _ =>
988+ throw((((blockHashHex + " is on an alternative chain #") + toString(withdrawBlockChainId)) + " that was not approved by majority. Wait for some blocks"))
989+ }
990+ if (if (isMainChain)
991+ then true
992+ else relatesToMainChain)
993+ then {
994+ let recipient = i.originCaller
995+ let recipientPkHash = take(drop(recipient.bytes, 2), PUBLIC_KEY_HASH_SIZE)
996+ let zeroAmountBytes = base58'11111111111111111111111111111111111111111111'
997+ let amountBytes = toBytes(amount)
998+ let elEventData = ((recipientPkHash + take(zeroAmountBytes, (size(zeroAmountBytes) - size(amountBytes)))) + amountBytes)
999+ let elEventDataDigest = blake2b256_16Kb(elEventData)
1000+ let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock)
1001+ let expectedRootHash = withdrawBlockMeta._6
1002+ if ((calculatedRootHash == expectedRootHash))
1003+ then {
1004+ let tokenId = fromBase58String(getStringValue(tokenIdKey))
1005+ let transfersKey = blockElToClTransfersKey(blockHashHex)
1006+[Reissue(tokenId, amount, true), ScriptTransfer(recipient, amount, tokenId), StringEntry(transfersKey, setOrFail(valueOrElse(getString(transfersKey), ""), transferIndexInBlock))]
1007+ }
1008+ else throw(((((("Expected root hash: " + toBase16String(expectedRootHash)) + ", got: ") + toBase16String(calculatedRootHash)) + ". Event data digest: ") + toBase64String(elEventDataDigest)))
1009+ }
1010+ else throw((("Expected " + blockHashHex) + " to be either on the main chain or relate to it"))
1011+ }
1012+ }
1013+ else throw("Strict value is not equal to itself.")
1014+ }
1015+
1016+
1017+
1018+@Callable(i)
1019+func setup (genesisBlockHashHex,minerRewardInGwei,stakingContractAddressB58,elBridgeAddressHex) = if (isContractSetup())
6751020 then throw("The contract has been already set up")
1021+ else if ((0 > minerRewardInGwei))
1022+ then throw("The miner reward must be nonnegative")
1023+ else {
1024+ let genesisBlockHash = fromBase16String(genesisBlockHashHex)
1025+ let emptyPk = base58'11111111111111111111111111111111'
1026+ let genesisMinerAddress = addressFromPublicKey(emptyPk)
1027+ let genesisEthRewardAddress = base58'11111111111111111111'
1028+ let genesisBlockReferenceHash = "0000000000000000000000000000000000000000000000000000000000000000"
1029+ let issue = Issue("UNIT0", "Native token", 0, 8, true)
1030+ let tokenId = calculateAssetId(issue)
1031+[mkBlockMetaEntry(genesisBlockHashHex, 0, genesisBlockReferenceHash, genesisMinerAddress, mainChainId, ""), StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), StringEntry(chainMetaKey(0), ("0," + genesisBlockHashHex)), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(stakingContractAddressKey, stakingContractAddressB58), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), IntegerEntry(prevRandaoHeightKey, 0), IntegerEntry(elToClTransfersEpochKey, 0), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, ("0x" + elBridgeAddressHex))]
1032+ }
1033+
1034+
1035+
1036+@Callable(i)
1037+func setupElToClTransfers (activationHeight,elBridgeAddressHex) = if (isDefined(getInteger(elToClTransfersEpochKey)))
1038+ then throw("EL to CL transfers feature was set up")
6761039 else {
677- let genesisBlockHash = fromBase16String(genesisBlockHashHex)
678- let emptyPk = base58'11111111111111111111111111111111'
679- let genesisMinerAddress = addressFromPublicKey(emptyPk)
680- let genesisEthRewardAddress = base58'11111111111111111111'
681- let genesisBlockReferenceHash = base58'11111111111111111111111111111111'
682- let genesisBlockMeta = (((toBytes(0) + toBytes(height)) + genesisBlockReferenceHash) + genesisMinerAddress.bytes)
683-[BinaryEntry((blockMetaK + genesisBlockHashHex), genesisBlockMeta), StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), StringEntry(chainMetaKey(0), ("0," + genesisBlockHashHex)), IntegerEntry(minerRewardKey, minerReward), StringEntry(stakingContractAddressKey, stakingContractAddressB58), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex)]
1040+ let issue = Issue("UNIT0", "Native token", 0, 8, true)
1041+ let tokenId = calculateAssetId(issue)
1042+[IntegerEntry(elToClTransfersEpochKey, activationHeight), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, ("0x" + elBridgeAddressHex))]
6841043 }
6851044
6861045

github/deemru/w8io/026f985 
139.03 ms