tx · FNjNKot193WRkSkpK9FPbckjMik1WXVhi6NsfbDPkqLL 3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch: -0.02500000 Waves 2024.07.03 14:50 [3177784] smart account 3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch > SELF 0.00000000 Waves
{ "type": 13, "id": "FNjNKot193WRkSkpK9FPbckjMik1WXVhi6NsfbDPkqLL", "fee": 2500000, "feeAssetId": null, "timestamp": 1720007437261, "version": 2, "chainId": 84, "sender": "3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch", "senderPublicKey": "3xjN6fjYDXBGUE1mcRw2Fvr4R6tEZnuJA98QFGF99sXd", "proofs": [ "2jyv2kJwAbdfxPCm7t1EZKTfHS5HySRFmFbeE1rmM39yrxyr1ueriqeXtUjiZRiZFJe1H2ZdaB4yHAScLKjFKBp3" ], "script": "base64:CAIsCAISBAoCCAgSBQoDCAgBEgUKAwgIARIGCgQBCAgBEgMKAQISABIFCgMIAQg/AAdJTlRfTUFYAP//////////fwAFV0FWRVMAgMLXLwALTUlOX0JBTEFOQ0UJAGgCAKCcAQUFV0FWRVMAA1NFUAIBLAAPQkxPQ0tfSEFTSF9TSVpFACAADEFERFJFU1NfU0laRQAaABB0aGlzRXBvY2hEYXRhS2V5Ag10aGlzRXBvY2hEYXRhAAxhbGxNaW5lcnNLZXkCCWFsbE1pbmVycwAObWFpbkNoYWluSWRLZXkCC21haW5DaGFpbklkAA5sYXN0Q2hhaW5JZEtleQILbGFzdENoYWluSWQAF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5AhRmaXJzdFZhbGlkQWx0Q2hhaW5JZAAObWluZXJSZXdhcmRLZXkCC21pbmVyUmV3YXJkABlzdGFraW5nQ29udHJhY3RBZGRyZXNzS2V5AhZzdGFraW5nQ29udHJhY3RBZGRyZXNzAApibG9ja01ldGFLAghibG9ja18weAARZmluYWxpemVkQmxvY2tLZXkCDmZpbmFsaXplZEJsb2NrAQNwYWQBAWkEAXMJAKQDAQUBaQQHJG1hdGNoMAkAsQIBBQFzAwkAAAIAAQUHJG1hdGNoMAkArAICAgcwMDAwMDAwBQFzAwkAAAIAAgUHJG1hdGNoMAkArAICAgYwMDAwMDAFAXMDCQAAAgADBQckbWF0Y2gwCQCsAgICBTAwMDAwBQFzAwkAAAIABAUHJG1hdGNoMAkArAICAgQwMDAwBQFzAwkAAAIABQUHJG1hdGNoMAkArAICAgMwMDAFAXMDCQAAAgAGBQckbWF0Y2gwCQCsAgICAjAwBQFzAwkAAAIABwUHJG1hdGNoMAkArAICAgEwBQFzBQFzAQxlcG9jaE1ldGFLZXkBBWVwb2NoCQCsAgICBmVwb2NoXwkBA3BhZAEFBWVwb2NoARRjaGFpbkZpcnN0QmxvY2tJZEtleQEHY2hhaW5JZAkArAICCQCsAgICBWNoYWluCQCkAwEFB2NoYWluSWQCCkZpcnN0QmxvY2sBDGNoYWluTWV0YUtleQEHY2hhaW5JZAkArAICAgZjaGFpbl8JAQNwYWQBBQdjaGFpbklkARJjaGFpbkxhc3RIZWlnaHRLZXkCB2NoYWluSWQFbWluZXIJAKwCAgkArAICCQCsAgICBmNoYWluXwkBA3BhZAEFB2NoYWluSWQCAV8JAKUIAQUFbWluZXIBDXN1cHBvcnRlcnNLZXkBB2NoYWluSWQJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgpTdXBwb3J0ZXJzARVtaW5lclJld2FyZEFkZHJlc3NLZXkBCW1pbmVyQWRkcgkArAICCQCsAgICBm1pbmVyXwUJbWluZXJBZGRyAg5fUmV3YXJkQWRkcmVzcwEKbWluZXJQa0tleQENcmV3YXJkQWRkcmVzcwkArAICCQCsAgICCG1pbmVyXzB4BQ1yZXdhcmRBZGRyZXNzAgNfUEsBD21pbmVyQ2hhaW5JZEtleQEFbWluZXIJAKwCAgkArAICAgZtaW5lcl8JAKUIAQUFbWluZXICCF9DaGFpbklkABZzdGFraW5nQ29udHJhY3RBZGRyZXNzBAckbWF0Y2gwCQCdCAIFBHRoaXMFGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUBcwkArAICAiJpbnZhbGlkIHN0YWtpbmcgY29udHJhY3QgYWRkcmVzczogBQFzCQEHQWRkcmVzcwEJARFAZXh0ck5hdGl2ZSgxMDUyKQIFBHRoaXMFGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkBEWdlbmVyYXRpbmdCYWxhbmNlAQdhZGRyZXNzBAckbWF0Y2gwCQCdCAIFFnN0YWtpbmdDb250cmFjdEFkZHJlc3MJAKwCAgIEJXNfXwkApQgBBQdhZGRyZXNzAwkAAQIFByRtYXRjaDACBlN0cmluZwQDc3RyBQckbWF0Y2gwBAlwYXJhbUxpc3QJALUJAgUDc3RyAgJfXwQKcHJldkhlaWdodAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCXBhcmFtTGlzdAABBAtwcmV2QmFsYW5jZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCXBhcmFtTGlzdAACBApuZXh0SGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJcGFyYW1MaXN0AAMEC25leHRCYWxhbmNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJcGFyYW1MaXN0AAQDCQBnAgUGaGVpZ2h0BQpuZXh0SGVpZ2h0BQtuZXh0QmFsYW5jZQMJAGcCBQZoZWlnaHQFCnByZXZIZWlnaHQFC3ByZXZCYWxhbmNlAAAAAAEJY2hhaW5NZXRhAQdjaGFpbklkBAFzCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEMY2hhaW5NZXRhS2V5AQUHY2hhaW5JZAQFaXRlbXMJALUJAgUBcwUDU0VQCQCUCgIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVpdGVtcwAACQCRAwIFBWl0ZW1zAAEAC21haW5DaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDm1haW5DaGFpbklkS2V5AAAACyR0MDI4MjkyODk1CQEJY2hhaW5NZXRhAQULbWFpbkNoYWluSWQAD21haW5DaGFpbkhlaWdodAgFCyR0MDI4MjkyODk1Al8xABJtYWluQ2hhaW5MYXN0QmxvY2sIBQskdDAyODI5Mjg5NQJfMgEJZXBvY2hNZXRhAQVlcG9jaAQHJG1hdGNoMAkAoggBCQEMZXBvY2hNZXRhS2V5AQUFZXBvY2gDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBAlmcmFnbWVudHMJALUJAgUBcwUDU0VQCQCVCgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUJZnJhZ21lbnRzAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmcmFnbWVudHMAAQkAkQMCBQlmcmFnbWVudHMAAgUEdW5pdAALJHQwMzEyNzM1OTEEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIWKEFkZHJlc3MsIEludCwgU3RyaW5nKQQBbQUHJG1hdGNoMAUBbQQHJG1hdGNoMQkAoggBBRB0aGlzRXBvY2hEYXRhS2V5AwkAAQIFByRtYXRjaDECBlN0cmluZwQQcmF3VGhpc0Vwb2NoRGF0YQUHJG1hdGNoMQQNdGhpc0Vwb2NoRGF0YQkAtQkCBRByYXdUaGlzRXBvY2hEYXRhBQNTRVAECXRoaXNFcG9jaAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDXRoaXNFcG9jaERhdGEAAAkAlQoDAwkAAAIFCXRoaXNFcG9jaAUGaGVpZ2h0CQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFDXRoaXNFcG9jaERhdGEAAQUEdW5pdAAAAgAJAJUKAwUEdW5pdAAAAgAADnRoaXNFcG9jaE1pbmVyCAULJHQwMzEyNzM1OTECXzEADHRoaXNFcG9jaFJlZggFCyR0MDMxMjczNTkxAl8yABJ0aGlzRXBvY2hMYXN0QmxvY2sIBQskdDAzMTI3MzU5MQJfMwAMYWxsTWluZXJzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFDGFsbE1pbmVyc0tleQIAAAlhbGxNaW5lcnMEByRtYXRjaDAFDGFsbE1pbmVyc1N0cgMJAAACAgAFByRtYXRjaDAFA25pbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEA3JhdwUHJG1hdGNoMAkAvAkCBQNyYXcFA1NFUAkAAgECC01hdGNoIGVycm9yAQlibG9ja01ldGEBB2Jsb2NrSWQEBG1ldGEJARFAZXh0ck5hdGl2ZSgxMDU3KQEJAKwCAgUKYmxvY2tNZXRhSwUHYmxvY2tJZAQLYmxvY2tIZWlnaHQJALEJAQUEbWV0YQQKYmxvY2tFcG9jaAkAsgkCBQRtZXRhAAgEC2Jsb2NrUGFyZW50CQDJAQIJAMoBAgUEbWV0YQAQBQ9CTE9DS19IQVNIX1NJWkUEDmJsb2NrR2VuZXJhdG9yCQDMAQIFBG1ldGEFDEFERFJFU1NfU0laRQkAlgoEBQtibG9ja0hlaWdodAUKYmxvY2tFcG9jaAULYmxvY2tQYXJlbnQFDmJsb2NrR2VuZXJhdG9yAQxsYXN0SGVpZ2h0QnkCBW1pbmVyB2NoYWluSWQEByRtYXRjaDAJAJ8IAQkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQFBW1pbmVyAwkAAQIFByRtYXRjaDACA0ludAQBaAUHJG1hdGNoMAUBaAQJYmxvY2tIYXNoCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgtMYXN0TWluZWRCeQkApQgBBQVtaW5lcggJAQlibG9ja01ldGEBBQlibG9ja0hhc2gCXzEACyR0MDQzNTE1MzE3BAloaXRTb3VyY2UEByRtYXRjaDAIBQlsYXN0QmxvY2sDdnJmAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEA3ZyZgUHJG1hdGNoMAUDdnJmCAUJbGFzdEJsb2NrE2dlbmVyYXRpb25TaWduYXR1cmUKAQxwcm9jZXNzTWluZXICBHByZXYFbWluZXIECyR0MDQ2NDk0NzEyBQRwcmV2BAlwcmV2RGVsYXkIBQskdDA0NjQ5NDcxMgJfMQQJcHJldk1pbmVyCAULJHQwNDY0OTQ3MTICXzIEEHByZXZUb3RhbEJhbGFuY2UIBQskdDA0NjQ5NDcxMgJfMwQKcHJldk1pbmVycwgFCyR0MDQ2NDk0NzEyAl80BAxtaW5lckFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBW1pbmVyBA93YXZlc0dlbkJhbGFuY2UICQDvBwEFDG1pbmVyQWRkcmVzcwpnZW5lcmF0aW5nBAxtaW5lckJhbGFuY2UJARFnZW5lcmF0aW5nQmFsYW5jZQEFDG1pbmVyQWRkcmVzcwMDCQBmAgULTUlOX0JBTEFOQ0UFD3dhdmVzR2VuQmFsYW5jZQYJAGcCAAAFDG1pbmVyQmFsYW5jZQUEcHJldgQJbmV4dERlbGF5CQCFBwIFDG1pbmVyQWRkcmVzcwUMbWluZXJCYWxhbmNlAwkAZgIFCXByZXZEZWxheQUJbmV4dERlbGF5CQCWCgQFCW5leHREZWxheQUFbWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UJAM0IAgUKcHJldk1pbmVycwUFbWluZXIJAJYKBAUJcHJldkRlbGF5BQlwcmV2TWluZXIJAGQCBRBwcmV2VG90YWxCYWxhbmNlBQxtaW5lckJhbGFuY2UJAM0IAgUKcHJldk1pbmVycwUFbWluZXIKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlgoEBQdJTlRfTUFYAgAAAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQxwcm9jZXNzTWluZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDUwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgANY29tcHV0ZWREZWxheQgFCyR0MDQzNTE1MzE3Al8xABFjb21wdXRlZEdlbmVyYXRvcggFCyR0MDQzNTE1MzE3Al8yABRjb21wdXRlZFRvdGFsQmFsYW5jZQgFCyR0MDQzNTE1MzE3Al8zAA5maWx0ZXJlZE1pbmVycwgFCyR0MDQzNTE1MzE3Al80ARNnZXRDaGFpbkxhc3RCbG9ja0lkAQdjaGFpbklkCAkBCWNoYWluTWV0YQEFB2NoYWluSWQCXzIACyR0MDUzODM1NDg1CQEJYmxvY2tNZXRhAQUSbWFpbkNoYWluTGFzdEJsb2NrAAdpZ25vcmVkCAULJHQwNTM4MzU0ODUCXzEADm1haW5DaGFpbkVwb2NoCAULJHQwNTM4MzU0ODUCXzIAE21haW5DaGFpblBhcmVudEhhc2gIBQskdDA1MzgzNTQ4NQJfMwASbWFpbkNoYWluR2VuZXJhdG9yCAULJHQwNTM4MzU0ODUCXzQBG2NhbGN1bGF0ZUZpbmFsaXplZEJsb2NrSGFzaAMIY3VyTWluZXIMY3VyUHJldkVwb2NoEGN1ckxhc3RCbG9ja0hhc2gEC29mZnNldHNfMTAwCQC8CQICZDo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OjoCAAQLaGFsZkJhbGFuY2UJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACCgEEc3RlcAIEcHJldgRuZXh0BAskdDA1ODUxNTkxNQUEcHJldgQJdGhpc0Vwb2NoCAULJHQwNTg1MTU5MTUCXzEEDHRvdGFsQmFsYW5jZQgFCyR0MDU4NTE1OTE1Al8yBA5tYXliZVNhZmVFcG9jaAgFCyR0MDU4NTE1OTE1Al8zBApwcmV2TWluZXJzCAULJHQwNTg1MTU5MTUCXzQEByRtYXRjaDAFDm1heWJlU2FmZUVwb2NoAwkAAQIFByRtYXRjaDACBFVuaXQECyR0MDU5NzM2MTM5AwkAAAIFCXRoaXNFcG9jaAUGaGVpZ2h0CQCVCgMFCGN1ck1pbmVyBQxjdXJQcmV2RXBvY2gFEGN1ckxhc3RCbG9ja0hhc2gJAQV2YWx1ZQEJAQllcG9jaE1ldGEBBQl0aGlzRXBvY2gEBW1pbmVyCAULJHQwNTk3MzYxMzkCXzEECXByZXZFcG9jaAgFCyR0MDU5NzM2MTM5Al8yBA1sYXN0QmxvY2tIYXNoCAULJHQwNTk3MzYxMzkCXzMDCQAAAgUJcHJldkVwb2NoAAAJAJYKBAUJdGhpc0Vwb2NoBQx0b3RhbEJhbGFuY2UFDWxhc3RCbG9ja0hhc2gFCWFsbE1pbmVycwQLJHQwNjI2NDY0NjYDCQEPY29udGFpbnNFbGVtZW50AgUKcHJldk1pbmVycwUFbWluZXIJAJQKAgUMdG90YWxCYWxhbmNlBQpwcmV2TWluZXJzCQCUCgIJAGQCBQx0b3RhbEJhbGFuY2UJARFnZW5lcmF0aW5nQmFsYW5jZQEFBW1pbmVyCQDMCAIFBW1pbmVyBQpwcmV2TWluZXJzBA9uZXdUb3RhbEJhbGFuY2UIBQskdDA2MjY0NjQ2NgJfMQQJbmV3TWluZXJzCAULJHQwNjI2NDY0NjYCXzIDCQBmAgUPbmV3VG90YWxCYWxhbmNlBQtoYWxmQmFsYW5jZQkAlgoEBQl0aGlzRXBvY2gFD25ld1RvdGFsQmFsYW5jZQUNbGFzdEJsb2NrSGFzaAUJYWxsTWluZXJzCQCWCgQFCXByZXZFcG9jaAUPbmV3VG90YWxCYWxhbmNlBQR1bml0BQluZXdNaW5lcnMFBHByZXYECyR0MDY3MDE2ODM0CgACJGwJAM4IAgULb2Zmc2V0c18xMDAFC29mZnNldHNfMTAwCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlgoEBQZoZWlnaHQAAAUEdW5pdAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQRzdGVwAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhVMaXN0IHNpemUgZXhjZWVkcyAyMDAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZABlAGYAZwBoAGkAagBrAGwAbQBuAG8AcABxAHIAcwB0AHUAdgB3AHgAeQB6AHsAfAB9AH4AfwCAAQCBAQCCAQCDAQCEAQCFAQCGAQCHAQCIAQCJAQCKAQCLAQCMAQCNAQCOAQCPAQCQAQCRAQCSAQCTAQCUAQCVAQCWAQCXAQCYAQCZAQCaAQCbAQCcAQCdAQCeAQCfAQCgAQChAQCiAQCjAQCkAQClAQCmAQCnAQCoAQCpAQCqAQCrAQCsAQCtAQCuAQCvAQCwAQCxAQCyAQCzAQC0AQC1AQC2AQC3AQC4AQC5AQC6AQC7AQC8AQC9AQC+AQC/AQDAAQDBAQDCAQDDAQDEAQDFAQDGAQDHAQDIAQQNZmFsbGJhY2tFcG9jaAgFCyR0MDY3MDE2ODM0Al8xBAx0b3RhbEJhbGFuY2UIBQskdDA2NzAxNjgzNAJfMgQVZmluYWxpemVkQmxvY2tIYXNoT3B0CAULJHQwNjcwMTY4MzQCXzMEBm1pbmVycwgFCyR0MDY3MDE2ODM0Al80BAckbWF0Y2gwBRVmaW5hbGl6ZWRCbG9ja0hhc2hPcHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBBJmaW5hbGl6ZWRCbG9ja0hhc2gFByRtYXRjaDAFEmZpbmFsaXplZEJsb2NrSGFzaAgJAQV2YWx1ZQEJAQllcG9jaE1ldGEBBQ1mYWxsYmFja0Vwb2NoAl8zARFzdXBwb3J0aW5nQmFsYW5jZQEHY2hhaW5JZAoBCmFkZEJhbGFuY2UCA2FjYwxnZW5lcmF0b3JTdHIECyR0MDcxMDQ3MTQwBQNhY2MEDHRvdGFsQmFsYW5jZQgFCyR0MDcxMDQ3MTQwAl8xBApnZW5lcmF0b3JzCAULJHQwNzEwNDcxNDACXzIECWdlbmVyYXRvcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUMZ2VuZXJhdG9yU3RyAwkBD2NvbnRhaW5zRWxlbWVudAIFCmdlbmVyYXRvcnMFCWdlbmVyYXRvcgUDYWNjBAdiYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQlnZW5lcmF0b3IJAJQKAgkAZAIFDHRvdGFsQmFsYW5jZQUHYmFsYW5jZQkAzQgCBQpnZW5lcmF0b3JzBQlnZW5lcmF0b3IEDWFsbEdlbmVyYXRvcnMJALwJAgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBDXN1cHBvcnRlcnNLZXkBBQdjaGFpbklkBQNTRVAECyR0MDc0NjI3NTI3CgACJGwFDWFsbEdlbmVyYXRvcnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQphZGRCYWxhbmNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhVMaXN0IHNpemUgZXhjZWVkcyAxMDAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZAQHYmFsYW5jZQgFCyR0MDc0NjI3NTI3Al8xBAJfZwgFCyR0MDc0NjI3NTI3Al8yBQdiYWxhbmNlAQ9pc0NvbnRyYWN0U2V0dXAACQEJaXNEZWZpbmVkAQkAnwgBBQ5taW5lclJld2FyZEtleQERZW5zdXJlTWluaW5nRXBvY2gBCWdlbmVyYXRvcgMJAQIhPQIJAKUIAQUJZ2VuZXJhdG9yBRFjb21wdXRlZEdlbmVyYXRvcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkA2AQBCAUJZ2VuZXJhdG9yBWJ5dGVzAhsgaXMgbm90IGFsbG93ZWQgdG8gbWluZSBpbiAJAKQDAQUGaGVpZ2h0AhEgZXBvY2guIEV4cGVjdGVkIAURY29tcHV0ZWRHZW5lcmF0b3IFBHVuaXQBEmlzUmVmZXJlbmNlQ29ycmVjdAIJcmVmZXJlbmNlCWxhc3RCbG9jawMJAAACBQlyZWZlcmVuY2UFCWxhc3RCbG9jawUEdW5pdAkAAgEJAKwCAgkArAICCQCsAgICMEV4cGVjdGVkIGEgcmVmZXJlbmNlIHRvIHRoZSBjaGFpbiBsYXN0IGJsb2NrOiAweAUJbGFzdEJsb2NrAgkuIEdvdDogMHgFCXJlZmVyZW5jZQEPY2hhaW5Jc0luYWN0aXZlAQdjaGFpbklkBAxmaXJzdEJsb2NrSWQJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEFB2NoYWluSWQEFGZpcnN0VmFsaWRBbHRDaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5AAADCQBmAgUUZmlyc3RWYWxpZEFsdENoYWluSWQFB2NoYWluSWQGCQBmAggJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMQgJAQlibG9ja01ldGEBBQxmaXJzdEJsb2NrSWQCXzEBDG1pbmVyQ2hhaW5JZAEFbWluZXIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBD21pbmVyQ2hhaW5JZEtleQEFBW1pbmVyCQCfCAEJAKwCAgIJY2hhaW5JZE9mCQClCAEFBW1pbmVyAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMJZ2VuZXJhdG9yD2V4cGVjdGVkQ2hhaW5JZBBjaGVja0hlaWdodEJsb2NrBA9oZWlnaHRJc0NvcnJlY3QEByRtYXRjaDAFEGNoZWNrSGVpZ2h0QmxvY2sDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAlibG9ja0hhc2gFByRtYXRjaDAEFGxhc3RNaW5lZEJsb2NrSGVpZ2h0CQEMbGFzdEhlaWdodEJ5AgUJZ2VuZXJhdG9yBQttYWluQ2hhaW5JZAkAZgIJAGQCCAkBCWJsb2NrTWV0YQEFCWJsb2NrSGFzaAJfMQABBRRsYXN0TWluZWRCbG9ja0hlaWdodAYEByRtYXRjaDAJAQxtaW5lckNoYWluSWQBBQlnZW5lcmF0b3IDCQABAgUHJG1hdGNoMAIDSW50BAljdXJyZW50SWQFByRtYXRjaDADAwkAAAIFCWN1cnJlbnRJZAUPZXhwZWN0ZWRDaGFpbklkBgMJAQ9jaGFpbklzSW5hY3RpdmUBBQljdXJyZW50SWQFD2hlaWdodElzQ29ycmVjdAcFBHVuaXQJAAIBCQCsAgICHG1pbmVyIGlzIG1pbmluZyBvdGhlciBjaGFpbiAJAKQDAQUJY3VycmVudElkBQR1bml0ARJlbnN1cmVDb3JyZWN0RXBvY2gBBWVwb2NoAwkAAAIFBWVwb2NoBQZoZWlnaHQFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAhpFeHBlY3RlZCBibG9jayBmcm9tIGVwb2NoIAkApAMBBQZoZWlnaHQCBi4gR290IAkApAMBBQVlcG9jaAEMYWRkU3VwcG9ydGVyAgdjaGFpbklkCWdlbmVyYXRvcgQNc3VwcG9ydGVyc1N0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBDXN1cHBvcnRlcnNLZXkBBQdjaGFpbklkBApzdXBwb3J0ZXJzCQC8CQIFDXN1cHBvcnRlcnNTdHIFA1NFUAMJAQ9jb250YWluc0VsZW1lbnQCBQpzdXBwb3J0ZXJzCQClCAEFCWdlbmVyYXRvcgUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1zdXBwb3J0ZXJzS2V5AQUHY2hhaW5JZAkArAICCQCsAgIFDXN1cHBvcnRlcnNTdHIFA1NFUAkApQgBBQlnZW5lcmF0b3IFA25pbAERdmFsaWRhdGVCbG9ja0hhc2gBBmhleFN0cgQMZGVjb2RlZEJ5dGVzCQDdBAEFBmhleFN0cgMJAQIhPQIJAMgBAQUMZGVjb2RlZEJ5dGVzACAJAAIBAhdpbnZhbGlkIGJsb2NrIGlkIGxlbmd0aAUGaGV4U3RyAR1nZXRVcGRhdGVGaW5hbGl6ZWRCbG9ja0FjdGlvbgMGY2FsbGVyD25ld0Jsb2NrSGFzaEhleAlwcmV2RXBvY2gEF2N1ckZpbmFsaXplZEJsb2NrSGVpZ2h0CAkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFEWZpbmFsaXplZEJsb2NrS2V5Al8xBBVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gJARtjYWxjdWxhdGVGaW5hbGl6ZWRCbG9ja0hhc2gDBQZjYWxsZXIFCXByZXZFcG9jaAUPbmV3QmxvY2tIYXNoSGV4AwkAAAIFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAUPbmV3QmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIFEWZpbmFsaXplZEJsb2NrS2V5BRVuZXdGaW5hbGl6ZWRCbG9ja0hhc2gFA25pbAMJAGYCCAkBCWJsb2NrTWV0YQEFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAJfMQUXY3VyRmluYWxpemVkQmxvY2tIZWlnaHQJAMwIAgkBC1N0cmluZ0VudHJ5AgURZmluYWxpemVkQmxvY2tLZXkFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAUDbmlsBQNuaWwHAWkBC2FwcGVuZEJsb2NrAgxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4AwkBAiE9AgUOdGhpc0Vwb2NoTWluZXIIBQFpDG9yaWdpbkNhbGxlcgQHJG1hdGNoMAUOdGhpc0Vwb2NoTWluZXIDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQKZXBvY2hNaW5lcgUHJG1hdGNoMAkAAgEJAKwCAgI5bm90IGFsbG93ZWQgdG8gZm9yZ2UgYmxvY2tzIGluIHRoaXMgZXBvY2gsIGV4cGVjdGVkIGZyb20gCQClCAEFCmVwb2NoTWluZXIJAAIBAkBub3QgYWxsb3dlZCB0byBmb3JnZSBibG9ja3MgaW4gdGhpcyBlcG9jaCwgZXBvY2ggbWluZXIgaXMgYWJzZW50BAdjaGFpbklkCQELdmFsdWVPckVsc2UCCQEMbWluZXJDaGFpbklkAQgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAQNJHQwMTA4MzMxMDg4NAkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMTA4MzMxMDg4NAJfMQQLbGFzdEJsb2NrSWQIBQ0kdDAxMDgzMzEwODg0Al8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAULbGFzdEJsb2NrSWQDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEEDG5ld0Jsb2NrTWV0YQkAywECCQDLAQIJAMsBAgkAmgMBBQ5uZXdDaGFpbkhlaWdodAkAmgMBBQZoZWlnaHQJAN0EAQULbGFzdEJsb2NrSWQICAUBaQxvcmlnaW5DYWxsZXIFYnl0ZXMECWJsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4CQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQdjaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKwCAgkArAICCQClCAEJAQV2YWx1ZQEFDnRoaXNFcG9jaE1pbmVyBQNTRVAJAKQDAQUMdGhpc0Vwb2NoUmVmBQNTRVAFDGJsb2NrSGFzaEhleAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD2V4dGVuZE1haW5DaGFpbgMMYmxvY2tIYXNoSGV4DHJlZmVyZW5jZUhleAVlcG9jaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFBWVwb2NoAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBQR1bml0AwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4EDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BRJtYWluQ2hhaW5MYXN0QmxvY2sDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQ5tYWluQ2hhaW5FcG9jaAUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkBBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFDm1haW5DaGFpbkVwb2NoBA5uZXdDaGFpbkhlaWdodAkAZAIFD21haW5DaGFpbkhlaWdodAABBAxuZXdCbG9ja01ldGEJAMsBAgkAywECCQDLAQIJAJoDAQUObmV3Q2hhaW5IZWlnaHQJAJoDAQUGaGVpZ2h0CQDdBAEFEm1haW5DaGFpbkxhc3RCbG9jawgIBQFpDG9yaWdpbkNhbGxlcgVieXRlcwkAzggCCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGNoYWluTWV0YUtleQEFC21haW5DaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgUNdGhpc0Vwb2NoTWV0YQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1zdGFydEFsdENoYWluAwxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEDSR0MDEzMDkzMTMxNzEJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgEDnJlZkNoYWluSGVpZ2h0CAUNJHQwMTMwOTMxMzE3MQJfMQQIcmVmRXBvY2gIBQ0kdDAxMzA5MzEzMTcxAl8yBAZyZWZSZWYIBQ0kdDAxMzA5MzEzMTcxAl8zBAxyZWZHZW5lcmF0b3IIBQ0kdDAxMzA5MzEzMTcxAl80BA5maW5hbGl6ZWRFcG9jaAgJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMgQIZXBvY2hSZWYDCQBnAgUIcmVmRXBvY2gFDmZpbmFsaXplZEVwb2NoBQhyZWZFcG9jaAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgIjY2FuIG5vdCBzdGFydCBhbHQgY2hhaW4gZnJvbSBlcG9jaCAJAKQDAQUIcmVmRXBvY2gCCCwgZXBvY2ggCQCkAwEFDmZpbmFsaXplZEVwb2NoAg0gaXMgZmluYWxpemVkBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBQxyZWZlcmVuY2VIZXgDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQKbmV3Q2hhaW5JZAkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUObGFzdENoYWluSWRLZXkAAAABBA9yZWZlcmVuY2VIZWlnaHQICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al8xBA5uZXdDaGFpbkhlaWdodAkAZAIFD3JlZmVyZW5jZUhlaWdodAABBAxuZXdCbG9ja01ldGEJAMsBAgkAywECCQDLAQIJAJoDAQUObmV3Q2hhaW5IZWlnaHQJAJoDAQUGaGVpZ2h0CQDdBAEFDHJlZmVyZW5jZUhleAgIBQFpDG9yaWdpbkNhbGxlcgVieXRlcwQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUIZXBvY2hSZWYFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUKbmV3Q2hhaW5JZAUMYmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQpuZXdDaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFCm5ld0NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQpuZXdDaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUPcmVmZXJlbmNlSGVpZ2h0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1zdXBwb3J0ZXJzS2V5AQUKbmV3Q2hhaW5JZAkApQgBCAUBaQxvcmlnaW5DYWxsZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFDmxhc3RDaGFpbklkS2V5BQpuZXdDaGFpbklkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEOZXh0ZW5kQWx0Q2hhaW4EB2NoYWluSWQMYmxvY2tIYXNoSGV4DHJlZmVyZW5jZUhleAVlcG9jaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFBWVwb2NoAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJANwEAQgJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQdjaGFpbklkAl8zAwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4EDSR0MDE1MzQwMTUzOTQJAQljaGFpbk1ldGEBBQdjaGFpbklkBAtjaGFpbkhlaWdodAgFDSR0MDE1MzQwMTUzOTQCXzEEDmNoYWluTGFzdEJsb2NrCAUNJHQwMTUzNDAxNTM5NAJfMgQOY2hlY2tSZWZlcmVuY2UJARJpc1JlZmVyZW5jZUNvcnJlY3QCBQxyZWZlcmVuY2VIZXgFDmNoYWluTGFzdEJsb2NrAwkAAAIFDmNoZWNrUmVmZXJlbmNlBQ5jaGVja1JlZmVyZW5jZQQObmV3Q2hhaW5IZWlnaHQJAGQCBQtjaGFpbkhlaWdodAABBAlwcmV2RXBvY2gICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al8yBBN1cGRhdGVNYWluQ2hhaW5EYXRhAwkAZgIJARFzdXBwb3J0aW5nQmFsYW5jZQEFB2NoYWluSWQJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACBBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFCXByZXZFcG9jaAkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5tYWluQ2hhaW5JZEtleQUHY2hhaW5JZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXZmlyc3RWYWxpZEFsdENoYWluSWRLZXkJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAAAQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawUDbmlsBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQlwcmV2RXBvY2gFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAQddXBkYXRlTWFpbkNoYWluTGFzdE1pbmVkQmxvY2sDAwkAAAIFE3VwZGF0ZU1haW5DaGFpbkRhdGEFA25pbAkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkBDG1pbmVyQ2hhaW5JZAEIBQFpDG9yaWdpbkNhbGxlcgAABQdjaGFpbklkBwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUHY2hhaW5JZAJfMQUDbmlsBQNuaWwEDG5ld0Jsb2NrTWV0YQkAywECCQDLAQIJAMsBAgkAmgMBBQ5uZXdDaGFpbkhlaWdodAkAmgMBBQZoZWlnaHQJAN0EAQUMcmVmZXJlbmNlSGV4CAgFAWkMb3JpZ2luQ2FsbGVyBWJ5dGVzCQDOCAIJAM4IAgkAzggCCQDMCAIJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4BQxuZXdCbG9ja01ldGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGNoYWluTWV0YUtleQEFB2NoYWluSWQJAKwCAgkArAICCQCkAwEFDm5ld0NoYWluSGVpZ2h0BQNTRVAFDGJsb2NrSGFzaEhleAkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPbWluZXJDaGFpbklkS2V5AQgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAUDbmlsBRN1cGRhdGVNYWluQ2hhaW5EYXRhCQEMYWRkU3VwcG9ydGVyAgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBR11cGRhdGVNYWluQ2hhaW5MYXN0TWluZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQRqb2luAQ1yZXdhcmRBZGRyZXNzCgESY2hlY2tSZXdhcmRBZGRyZXNzAQdhZGRyZXNzBAckbWF0Y2gwCQChCAEJAQptaW5lclBrS2V5AQUHYWRkcmVzcwMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJwawUHJG1hdGNoMAMJAAACBQJwawgFAWkVb3JpZ2luQ2FsbGVyUHVibGljS2V5BQR1bml0CQACAQkArAICCQCsAgIJAKwCAgIRTDIgbWluZXIgYWRkcmVzcyAFB2FkZHJlc3MCGCBpcyBhbHJlYWR5IGxpbmtlZCB3aXRoIAkA2AQBBQJwawUEdW5pdAMJAQEhAQkBD2lzQ29udHJhY3RTZXR1cAAJAAIBAh9UaGUgY29udHJhY3QgaGFzIG5vdCB5ZXQgc2V0IHVwAwkAZgIFC01JTl9CQUxBTkNFCAkA7wcBCAUBaQxvcmlnaW5DYWxsZXIKZ2VuZXJhdGluZwkAAgEJAKwCAgkArAICCQCsAgICIUluc3VmZmljaWVudCBnZW5lcmF0aW5nIGJhbGFuY2U6IAkApAMBCAkA7wcBCAUBaQxvcmlnaW5DYWxsZXIKZ2VuZXJhdGluZwIMLiBSZXF1aXJlZDogCQCkAwEFC01JTl9CQUxBTkNFAwkBAiE9AgkAyAEBBQ1yZXdhcmRBZGRyZXNzABQJAAIBAiVyZXdhcmRBZGRyZXNzIHNob3VsZCBiZSBhbiBMMiBhZGRyZXNzAwkAZwIJAJADAQUJYWxsTWluZXJzADIJAAIBAg90b28gbWFueSBtaW5lcnMKAQ5jaGVja0V4aXN0ZW5jZQIGZXhpc3RzBW1pbmVyAwUGZXhpc3RzBgkAAAIFBW1pbmVyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQNYWxyZWFkeUV4aXN0cwoAAiRsBQlhbGxNaW5lcnMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBwoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEOY2hlY2tFeGlzdGVuY2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDUwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgMFDWFscmVhZHlFeGlzdHMFA25pbAQIbmV3TWluZXIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBBByZXdhcmRBZGRyZXNzSGV4CQDcBAEFDXJld2FyZEFkZHJlc3MEBWNoZWNrCQESY2hlY2tSZXdhcmRBZGRyZXNzAQUQcmV3YXJkQWRkcmVzc0hleAMJAAACBQVjaGVjawUFY2hlY2sECW5ld01pbmVycwMJAAACCQCQAwEFCWFsbE1pbmVycwAABQhuZXdNaW5lcgkArAICCQCsAgIFDGFsbE1pbmVyc1N0cgUDU0VQBQhuZXdNaW5lcgQYZGVsZXRlT2xkUmV3YXJkQWRkcmVzc1BrBAckbWF0Y2gwCQCiCAEJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQhuZXdNaW5lcgMJAAECBQckbWF0Y2gwAgZTdHJpbmcECm9sZEFkZHJlc3MFByRtYXRjaDADCQAAAgUKb2xkQWRkcmVzcwkA3AQBBQ1yZXdhcmRBZGRyZXNzBQNuaWwJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBCm1pbmVyUGtLZXkBBQpvbGRBZGRyZXNzBQNuaWwFA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFDGFsbE1pbmVyc0tleQUJbmV3TWluZXJzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQhuZXdNaW5lcgkArAICAgIweAUQcmV3YXJkQWRkcmVzc0hleAkAzAgCCQELQmluYXJ5RW50cnkCCQEKbWluZXJQa0tleQEFEHJld2FyZEFkZHJlc3NIZXgIBQFpFW9yaWdpbkNhbGxlclB1YmxpY0tleQUDbmlsBRhkZWxldGVPbGRSZXdhcmRBZGRyZXNzUGsJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEFbGVhdmUABAxsZWF2aW5nTWluZXIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCgEQc2tpcExlYXZpbmdNaW5lcgIDYWNjBW1pbmVyAwkAAAIFBW1pbmVyBQxsZWF2aW5nTWluZXIFA2FjYwkAzQgCBQNhY2MFBW1pbmVyBA9yZW1haW5pbmdNaW5lcnMKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARBza2lwTGVhdmluZ01pbmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIEDXJld2FyZEFkZHJLZXkJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQxsZWF2aW5nTWluZXIEEXByZXZSZXdhcmRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhpcwUNcmV3YXJkQWRkcktleQIWbWluZXIgaGFzIG5ldmVyIGpvaW5lZAMJAAACBQ50aGlzRXBvY2hNaW5lcggFAWkMb3JpZ2luQ2FsbGVyCQACAQIcZGVzaWduYXRlZCBtaW5lciBjYW4ndCBsZWF2ZQkAzAgCCQELU3RyaW5nRW50cnkCBQxhbGxNaW5lcnNLZXkJALoJAgUPcmVtYWluaW5nTWluZXJzBQNTRVAJAMwIAgkBC0RlbGV0ZUVudHJ5AQUNcmV3YXJkQWRkcktleQkAzAgCCQELRGVsZXRlRW50cnkBCQEKbWluZXJQa0tleQEFEXByZXZSZXdhcmRBZGRyZXNzBQNuaWwBaQEFc2V0dXADE2dlbmVzaXNCbG9ja0hhc2hIZXgLbWluZXJSZXdhcmQZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0I1OAMJAQ9pc0NvbnRyYWN0U2V0dXAACQACAQIkVGhlIGNvbnRyYWN0IGhhcyBiZWVuIGFscmVhZHkgc2V0IHVwBBBnZW5lc2lzQmxvY2tIYXNoCQDdBAEFE2dlbmVzaXNCbG9ja0hhc2hIZXgEB2VtcHR5UGsBIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBNnZW5lc2lzTWluZXJBZGRyZXNzCQCnCAEFB2VtcHR5UGsEF2dlbmVzaXNFdGhSZXdhcmRBZGRyZXNzARQAAAAAAAAAAAAAAAAAAAAAAAAAAAQZZ2VuZXNpc0Jsb2NrUmVmZXJlbmNlSGFzaAEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEGdlbmVzaXNCbG9ja01ldGEJAMsBAgkAywECCQDLAQIJAJoDAQAACQCaAwEFBmhlaWdodAUZZ2VuZXNpc0Jsb2NrUmVmZXJlbmNlSGFzaAgFE2dlbmVzaXNNaW5lckFkZHJlc3MFYnl0ZXMJAMwIAgkBC0JpbmFyeUVudHJ5AgkArAICBQpibG9ja01ldGFLBRNnZW5lc2lzQmxvY2tIYXNoSGV4BRBnZW5lc2lzQmxvY2tNZXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEAAAUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCCQELU3RyaW5nRW50cnkCCQEMY2hhaW5NZXRhS2V5AQAACQCsAgICAjAsBRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5taW5lclJld2FyZEtleQULbWluZXJSZXdhcmQJAMwIAgkBC1N0cmluZ0VudHJ5AgUZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0tleQUZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0I1OAkAzAgCCQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkApQgBBRNnZW5lc2lzTWluZXJBZGRyZXNzAgMsMCwFE2dlbmVzaXNCbG9ja0hhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgURZmluYWxpemVkQmxvY2tLZXkFE2dlbmVzaXNCbG9ja0hhc2hIZXgFA25pbACcCbFw", "height": 3177784, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: xnYL9g17m4sTjSP8JEK3CgbfaRPrevXY7fUYC4vtnyu Next: GPDrfDQ2Jpsvk5nSwYoCMcd5MEHcZSCcD2kGPSNpoy1M Diff:
Old | New | Differences | |
---|---|---|---|
278 | 278 | } | |
279 | 279 | } | |
280 | 280 | ||
281 | - | let | |
281 | + | let $t067016834 = { | |
282 | 282 | let $l = (offsets_100 ++ offsets_100) | |
283 | 283 | let $s = size($l) | |
284 | 284 | let $acc0 = $Tuple4(height, 0, unit, nil) | |
292 | 292 | ||
293 | 293 | $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) | |
294 | 294 | } | |
295 | - | let fallbackEpoch = res._1 | |
296 | - | valueOrElse(res._3, value(epochMeta(fallbackEpoch))._3) | |
295 | + | let fallbackEpoch = $t067016834._1 | |
296 | + | let totalBalance = $t067016834._2 | |
297 | + | let finalizedBlockHashOpt = $t067016834._3 | |
298 | + | let miners = $t067016834._4 | |
299 | + | match finalizedBlockHashOpt { | |
300 | + | case finalizedBlockHash: String => | |
301 | + | finalizedBlockHash | |
302 | + | case _ => | |
303 | + | value(epochMeta(fallbackEpoch))._3 | |
304 | + | } | |
297 | 305 | } | |
298 | 306 | ||
299 | 307 | ||
300 | 308 | func supportingBalance (chainId) = { | |
301 | 309 | func addBalance (acc,generatorStr) = { | |
302 | - | let $ | |
303 | - | let totalBalance = $ | |
304 | - | let generators = $ | |
310 | + | let $t071047140 = acc | |
311 | + | let totalBalance = $t071047140._1 | |
312 | + | let generators = $t071047140._2 | |
305 | 313 | let generator = addressFromStringValue(generatorStr) | |
306 | 314 | if (containsElement(generators, generator)) | |
307 | 315 | then acc | |
312 | 320 | } | |
313 | 321 | ||
314 | 322 | let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP) | |
315 | - | let $ | |
323 | + | let $t074627527 = { | |
316 | 324 | let $l = allGenerators | |
317 | 325 | let $s = size($l) | |
318 | 326 | let $acc0 = $Tuple2(0, nil) | |
326 | 334 | ||
327 | 335 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
328 | 336 | } | |
329 | - | let balance = $ | |
330 | - | let _g = $ | |
337 | + | let balance = $t074627527._1 | |
338 | + | let _g = $t074627527._2 | |
331 | 339 | balance | |
332 | 340 | } | |
333 | 341 | ||
423 | 431 | } | |
424 | 432 | else { | |
425 | 433 | let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId) | |
426 | - | let $ | |
427 | - | let chainHeight = $ | |
428 | - | let lastBlockId = $ | |
434 | + | let $t01083310884 = chainMeta(chainId) | |
435 | + | let chainHeight = $t01083310884._1 | |
436 | + | let lastBlockId = $t01083310884._2 | |
429 | 437 | let checkReference = isReferenceCorrect(referenceHex, lastBlockId) | |
430 | 438 | if ((checkReference == checkReference)) | |
431 | 439 | then { | |
483 | 491 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
484 | 492 | if ((checkGenerator == checkGenerator)) | |
485 | 493 | then { | |
486 | - | let $ | |
487 | - | let refChainHeight = $ | |
488 | - | let refEpoch = $ | |
489 | - | let refRef = $ | |
490 | - | let refGenerator = $ | |
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 | |
491 | 499 | let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2 | |
492 | 500 | let epochRef = if ((refEpoch >= finalizedEpoch)) | |
493 | 501 | then refEpoch | |
527 | 535 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._3)) | |
528 | 536 | if ((checkChain == checkChain)) | |
529 | 537 | then { | |
530 | - | let $ | |
531 | - | let chainHeight = $ | |
532 | - | let chainLastBlock = $ | |
538 | + | let $t01534015394 = chainMeta(chainId) | |
539 | + | let chainHeight = $t01534015394._1 | |
540 | + | let chainLastBlock = $t01534015394._2 | |
533 | 541 | let checkReference = isReferenceCorrect(referenceHex, chainLastBlock) | |
534 | 542 | if ((checkReference == checkReference)) | |
535 | 543 | then { |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 8 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let INT_MAX = 9223372036854775807 | |
5 | 5 | ||
6 | 6 | let WAVES = 100000000 | |
7 | 7 | ||
8 | 8 | let MIN_BALANCE = (20000 * WAVES) | |
9 | 9 | ||
10 | 10 | let SEP = "," | |
11 | 11 | ||
12 | 12 | let BLOCK_HASH_SIZE = 32 | |
13 | 13 | ||
14 | 14 | let ADDRESS_SIZE = 26 | |
15 | 15 | ||
16 | 16 | let thisEpochDataKey = "thisEpochData" | |
17 | 17 | ||
18 | 18 | let allMinersKey = "allMiners" | |
19 | 19 | ||
20 | 20 | let mainChainIdKey = "mainChainId" | |
21 | 21 | ||
22 | 22 | let lastChainIdKey = "lastChainId" | |
23 | 23 | ||
24 | 24 | let firstValidAltChainIdKey = "firstValidAltChainId" | |
25 | 25 | ||
26 | 26 | let minerRewardKey = "minerReward" | |
27 | 27 | ||
28 | 28 | let stakingContractAddressKey = "stakingContractAddress" | |
29 | 29 | ||
30 | 30 | let blockMetaK = "block_0x" | |
31 | 31 | ||
32 | 32 | let finalizedBlockKey = "finalizedBlock" | |
33 | 33 | ||
34 | 34 | func pad (i) = { | |
35 | 35 | let s = toString(i) | |
36 | 36 | match size(s) { | |
37 | 37 | case _ => | |
38 | 38 | if ((1 == $match0)) | |
39 | 39 | then ("0000000" + s) | |
40 | 40 | else if ((2 == $match0)) | |
41 | 41 | then ("000000" + s) | |
42 | 42 | else if ((3 == $match0)) | |
43 | 43 | then ("00000" + s) | |
44 | 44 | else if ((4 == $match0)) | |
45 | 45 | then ("0000" + s) | |
46 | 46 | else if ((5 == $match0)) | |
47 | 47 | then ("000" + s) | |
48 | 48 | else if ((6 == $match0)) | |
49 | 49 | then ("00" + s) | |
50 | 50 | else if ((7 == $match0)) | |
51 | 51 | then ("0" + s) | |
52 | 52 | else s | |
53 | 53 | } | |
54 | 54 | } | |
55 | 55 | ||
56 | 56 | ||
57 | 57 | func epochMetaKey (epoch) = ("epoch_" + pad(epoch)) | |
58 | 58 | ||
59 | 59 | ||
60 | 60 | func chainFirstBlockIdKey (chainId) = (("chain" + toString(chainId)) + "FirstBlock") | |
61 | 61 | ||
62 | 62 | ||
63 | 63 | func chainMetaKey (chainId) = ("chain_" + pad(chainId)) | |
64 | 64 | ||
65 | 65 | ||
66 | 66 | func chainLastHeightKey (chainId,miner) = ((("chain_" + pad(chainId)) + "_") + toString(miner)) | |
67 | 67 | ||
68 | 68 | ||
69 | 69 | func supportersKey (chainId) = (("chain" + toString(chainId)) + "Supporters") | |
70 | 70 | ||
71 | 71 | ||
72 | 72 | func minerRewardAddressKey (minerAddr) = (("miner_" + minerAddr) + "_RewardAddress") | |
73 | 73 | ||
74 | 74 | ||
75 | 75 | func minerPkKey (rewardAddress) = (("miner_0x" + rewardAddress) + "_PK") | |
76 | 76 | ||
77 | 77 | ||
78 | 78 | func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId") | |
79 | 79 | ||
80 | 80 | ||
81 | 81 | let stakingContractAddress = match getString(this, stakingContractAddressKey) { | |
82 | 82 | case s: String => | |
83 | 83 | valueOrErrorMessage(addressFromString(s), ("invalid staking contract address: " + s)) | |
84 | 84 | case _ => | |
85 | 85 | Address(getBinaryValue(this, stakingContractAddressKey)) | |
86 | 86 | } | |
87 | 87 | ||
88 | 88 | func generatingBalance (address) = match getString(stakingContractAddress, ("%s__" + toString(address))) { | |
89 | 89 | case str: String => | |
90 | 90 | let paramList = split(str, "__") | |
91 | 91 | let prevHeight = parseIntValue(paramList[1]) | |
92 | 92 | let prevBalance = parseIntValue(paramList[2]) | |
93 | 93 | let nextHeight = parseIntValue(paramList[3]) | |
94 | 94 | let nextBalance = parseIntValue(paramList[4]) | |
95 | 95 | if ((height >= nextHeight)) | |
96 | 96 | then nextBalance | |
97 | 97 | else if ((height >= prevHeight)) | |
98 | 98 | then prevBalance | |
99 | 99 | else 0 | |
100 | 100 | case _ => | |
101 | 101 | 0 | |
102 | 102 | } | |
103 | 103 | ||
104 | 104 | ||
105 | 105 | func chainMeta (chainId) = { | |
106 | 106 | let s = getStringValue(chainMetaKey(chainId)) | |
107 | 107 | let items = split(s, SEP) | |
108 | 108 | $Tuple2(parseIntValue(items[0]), items[1]) | |
109 | 109 | } | |
110 | 110 | ||
111 | 111 | ||
112 | 112 | let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0) | |
113 | 113 | ||
114 | 114 | let $t028292895 = chainMeta(mainChainId) | |
115 | 115 | ||
116 | 116 | let mainChainHeight = $t028292895._1 | |
117 | 117 | ||
118 | 118 | let mainChainLastBlock = $t028292895._2 | |
119 | 119 | ||
120 | 120 | func epochMeta (epoch) = match getString(epochMetaKey(epoch)) { | |
121 | 121 | case s: String => | |
122 | 122 | let fragments = split(s, SEP) | |
123 | 123 | $Tuple3(addressFromStringValue(fragments[0]), parseIntValue(fragments[1]), fragments[2]) | |
124 | 124 | case _ => | |
125 | 125 | unit | |
126 | 126 | } | |
127 | 127 | ||
128 | 128 | ||
129 | 129 | let $t031273591 = match epochMeta(height) { | |
130 | 130 | case m: (Address, Int, String) => | |
131 | 131 | m | |
132 | 132 | case _ => | |
133 | 133 | match getString(thisEpochDataKey) { | |
134 | 134 | case rawThisEpochData: String => | |
135 | 135 | let thisEpochData = split(rawThisEpochData, SEP) | |
136 | 136 | let thisEpoch = parseIntValue(thisEpochData[0]) | |
137 | 137 | $Tuple3(if ((thisEpoch == height)) | |
138 | 138 | then addressFromStringValue(thisEpochData[1]) | |
139 | 139 | else unit, 0, "") | |
140 | 140 | case _ => | |
141 | 141 | $Tuple3(unit, 0, "") | |
142 | 142 | } | |
143 | 143 | } | |
144 | 144 | ||
145 | 145 | let thisEpochMiner = $t031273591._1 | |
146 | 146 | ||
147 | 147 | let thisEpochRef = $t031273591._2 | |
148 | 148 | ||
149 | 149 | let thisEpochLastBlock = $t031273591._3 | |
150 | 150 | ||
151 | 151 | let allMinersStr = valueOrElse(getString(allMinersKey), "") | |
152 | 152 | ||
153 | 153 | let allMiners = match allMinersStr { | |
154 | 154 | case _ => | |
155 | 155 | if (("" == $match0)) | |
156 | 156 | then nil | |
157 | 157 | else if ($isInstanceOf($match0, "String")) | |
158 | 158 | then { | |
159 | 159 | let raw = $match0 | |
160 | 160 | split_4C(raw, SEP) | |
161 | 161 | } | |
162 | 162 | else throw("Match error") | |
163 | 163 | } | |
164 | 164 | ||
165 | 165 | func blockMeta (blockId) = { | |
166 | 166 | let meta = getBinaryValue((blockMetaK + blockId)) | |
167 | 167 | let blockHeight = toInt(meta) | |
168 | 168 | let blockEpoch = toInt(meta, 8) | |
169 | 169 | let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE) | |
170 | 170 | let blockGenerator = takeRight(meta, ADDRESS_SIZE) | |
171 | 171 | $Tuple4(blockHeight, blockEpoch, blockParent, blockGenerator) | |
172 | 172 | } | |
173 | 173 | ||
174 | 174 | ||
175 | 175 | func lastHeightBy (miner,chainId) = match getInteger(chainLastHeightKey(chainId, miner)) { | |
176 | 176 | case h: Int => | |
177 | 177 | h | |
178 | 178 | case _ => | |
179 | 179 | let blockHash = getStringValue(((("chain" + toString(chainId)) + "LastMinedBy") + toString(miner))) | |
180 | 180 | blockMeta(blockHash)._1 | |
181 | 181 | } | |
182 | 182 | ||
183 | 183 | ||
184 | 184 | let $t043515317 = { | |
185 | 185 | let hitSource = match lastBlock.vrf { | |
186 | 186 | case vrf: ByteVector => | |
187 | 187 | vrf | |
188 | 188 | case _ => | |
189 | 189 | lastBlock.generationSignature | |
190 | 190 | } | |
191 | 191 | func processMiner (prev,miner) = { | |
192 | 192 | let $t046494712 = prev | |
193 | 193 | let prevDelay = $t046494712._1 | |
194 | 194 | let prevMiner = $t046494712._2 | |
195 | 195 | let prevTotalBalance = $t046494712._3 | |
196 | 196 | let prevMiners = $t046494712._4 | |
197 | 197 | let minerAddress = addressFromStringValue(miner) | |
198 | 198 | let wavesGenBalance = wavesBalance(minerAddress).generating | |
199 | 199 | let minerBalance = generatingBalance(minerAddress) | |
200 | 200 | if (if ((MIN_BALANCE > wavesGenBalance)) | |
201 | 201 | then true | |
202 | 202 | else (0 >= minerBalance)) | |
203 | 203 | then prev | |
204 | 204 | else { | |
205 | 205 | let nextDelay = calculateDelay(minerAddress, minerBalance) | |
206 | 206 | if ((prevDelay > nextDelay)) | |
207 | 207 | then $Tuple4(nextDelay, miner, (prevTotalBalance + minerBalance), (prevMiners :+ miner)) | |
208 | 208 | else $Tuple4(prevDelay, prevMiner, (prevTotalBalance + minerBalance), (prevMiners :+ miner)) | |
209 | 209 | } | |
210 | 210 | } | |
211 | 211 | ||
212 | 212 | let $l = allMiners | |
213 | 213 | let $s = size($l) | |
214 | 214 | let $acc0 = $Tuple4(INT_MAX, "", 0, nil) | |
215 | 215 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
216 | 216 | then $a | |
217 | 217 | else processMiner($a, $l[$i]) | |
218 | 218 | ||
219 | 219 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
220 | 220 | then $a | |
221 | 221 | else throw("List size exceeds 50") | |
222 | 222 | ||
223 | 223 | $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) | |
224 | 224 | } | |
225 | 225 | ||
226 | 226 | let computedDelay = $t043515317._1 | |
227 | 227 | ||
228 | 228 | let computedGenerator = $t043515317._2 | |
229 | 229 | ||
230 | 230 | let computedTotalBalance = $t043515317._3 | |
231 | 231 | ||
232 | 232 | let filteredMiners = $t043515317._4 | |
233 | 233 | ||
234 | 234 | func getChainLastBlockId (chainId) = chainMeta(chainId)._2 | |
235 | 235 | ||
236 | 236 | ||
237 | 237 | let $t053835485 = blockMeta(mainChainLastBlock) | |
238 | 238 | ||
239 | 239 | let ignored = $t053835485._1 | |
240 | 240 | ||
241 | 241 | let mainChainEpoch = $t053835485._2 | |
242 | 242 | ||
243 | 243 | let mainChainParentHash = $t053835485._3 | |
244 | 244 | ||
245 | 245 | let mainChainGenerator = $t053835485._4 | |
246 | 246 | ||
247 | 247 | func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = { | |
248 | 248 | let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "") | |
249 | 249 | let halfBalance = (computedTotalBalance / 2) | |
250 | 250 | func step (prev,next) = { | |
251 | 251 | let $t058515915 = prev | |
252 | 252 | let thisEpoch = $t058515915._1 | |
253 | 253 | let totalBalance = $t058515915._2 | |
254 | 254 | let maybeSafeEpoch = $t058515915._3 | |
255 | 255 | let prevMiners = $t058515915._4 | |
256 | 256 | match maybeSafeEpoch { | |
257 | 257 | case _: Unit => | |
258 | 258 | let $t059736139 = if ((thisEpoch == height)) | |
259 | 259 | then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash) | |
260 | 260 | else value(epochMeta(thisEpoch)) | |
261 | 261 | let miner = $t059736139._1 | |
262 | 262 | let prevEpoch = $t059736139._2 | |
263 | 263 | let lastBlockHash = $t059736139._3 | |
264 | 264 | if ((prevEpoch == 0)) | |
265 | 265 | then $Tuple4(thisEpoch, totalBalance, lastBlockHash, allMiners) | |
266 | 266 | else { | |
267 | 267 | let $t062646466 = if (containsElement(prevMiners, miner)) | |
268 | 268 | then $Tuple2(totalBalance, prevMiners) | |
269 | 269 | else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners) | |
270 | 270 | let newTotalBalance = $t062646466._1 | |
271 | 271 | let newMiners = $t062646466._2 | |
272 | 272 | if ((newTotalBalance > halfBalance)) | |
273 | 273 | then $Tuple4(thisEpoch, newTotalBalance, lastBlockHash, allMiners) | |
274 | 274 | else $Tuple4(prevEpoch, newTotalBalance, unit, newMiners) | |
275 | 275 | } | |
276 | 276 | case _ => | |
277 | 277 | prev | |
278 | 278 | } | |
279 | 279 | } | |
280 | 280 | ||
281 | - | let | |
281 | + | let $t067016834 = { | |
282 | 282 | let $l = (offsets_100 ++ offsets_100) | |
283 | 283 | let $s = size($l) | |
284 | 284 | let $acc0 = $Tuple4(height, 0, unit, nil) | |
285 | 285 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
286 | 286 | then $a | |
287 | 287 | else step($a, $l[$i]) | |
288 | 288 | ||
289 | 289 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
290 | 290 | then $a | |
291 | 291 | else throw("List size exceeds 200") | |
292 | 292 | ||
293 | 293 | $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) | |
294 | 294 | } | |
295 | - | let fallbackEpoch = res._1 | |
296 | - | valueOrElse(res._3, value(epochMeta(fallbackEpoch))._3) | |
295 | + | let fallbackEpoch = $t067016834._1 | |
296 | + | let totalBalance = $t067016834._2 | |
297 | + | let finalizedBlockHashOpt = $t067016834._3 | |
298 | + | let miners = $t067016834._4 | |
299 | + | match finalizedBlockHashOpt { | |
300 | + | case finalizedBlockHash: String => | |
301 | + | finalizedBlockHash | |
302 | + | case _ => | |
303 | + | value(epochMeta(fallbackEpoch))._3 | |
304 | + | } | |
297 | 305 | } | |
298 | 306 | ||
299 | 307 | ||
300 | 308 | func supportingBalance (chainId) = { | |
301 | 309 | func addBalance (acc,generatorStr) = { | |
302 | - | let $ | |
303 | - | let totalBalance = $ | |
304 | - | let generators = $ | |
310 | + | let $t071047140 = acc | |
311 | + | let totalBalance = $t071047140._1 | |
312 | + | let generators = $t071047140._2 | |
305 | 313 | let generator = addressFromStringValue(generatorStr) | |
306 | 314 | if (containsElement(generators, generator)) | |
307 | 315 | then acc | |
308 | 316 | else { | |
309 | 317 | let balance = generatingBalance(generator) | |
310 | 318 | $Tuple2((totalBalance + balance), (generators :+ generator)) | |
311 | 319 | } | |
312 | 320 | } | |
313 | 321 | ||
314 | 322 | let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP) | |
315 | - | let $ | |
323 | + | let $t074627527 = { | |
316 | 324 | let $l = allGenerators | |
317 | 325 | let $s = size($l) | |
318 | 326 | let $acc0 = $Tuple2(0, nil) | |
319 | 327 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
320 | 328 | then $a | |
321 | 329 | else addBalance($a, $l[$i]) | |
322 | 330 | ||
323 | 331 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
324 | 332 | then $a | |
325 | 333 | else throw("List size exceeds 100") | |
326 | 334 | ||
327 | 335 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
328 | 336 | } | |
329 | - | let balance = $ | |
330 | - | let _g = $ | |
337 | + | let balance = $t074627527._1 | |
338 | + | let _g = $t074627527._2 | |
331 | 339 | balance | |
332 | 340 | } | |
333 | 341 | ||
334 | 342 | ||
335 | 343 | func isContractSetup () = isDefined(getInteger(minerRewardKey)) | |
336 | 344 | ||
337 | 345 | ||
338 | 346 | func ensureMiningEpoch (generator) = if ((toString(generator) != computedGenerator)) | |
339 | 347 | then throw(((((toBase58String(generator.bytes) + " is not allowed to mine in ") + toString(height)) + " epoch. Expected ") + computedGenerator)) | |
340 | 348 | else unit | |
341 | 349 | ||
342 | 350 | ||
343 | 351 | func isReferenceCorrect (reference,lastBlock) = if ((reference == lastBlock)) | |
344 | 352 | then unit | |
345 | 353 | else throw(((("Expected a reference to the chain last block: 0x" + lastBlock) + ". Got: 0x") + reference)) | |
346 | 354 | ||
347 | 355 | ||
348 | 356 | func chainIsInactive (chainId) = { | |
349 | 357 | let firstBlockId = getStringValue(chainFirstBlockIdKey(chainId)) | |
350 | 358 | let firstValidAltChainId = valueOrElse(getInteger(firstValidAltChainIdKey), 0) | |
351 | 359 | if ((firstValidAltChainId > chainId)) | |
352 | 360 | then true | |
353 | 361 | else (blockMeta(getStringValue(finalizedBlockKey))._1 > blockMeta(firstBlockId)._1) | |
354 | 362 | } | |
355 | 363 | ||
356 | 364 | ||
357 | 365 | func minerChainId (miner) = valueOrElse(getInteger(minerChainIdKey(miner)), getInteger(("chainIdOf" + toString(miner)))) | |
358 | 366 | ||
359 | 367 | ||
360 | 368 | func ensureExpectedOrInactiveChain (generator,expectedChainId,checkHeightBlock) = { | |
361 | 369 | let heightIsCorrect = match checkHeightBlock { | |
362 | 370 | case blockHash: String => | |
363 | 371 | let lastMinedBlockHeight = lastHeightBy(generator, mainChainId) | |
364 | 372 | ((blockMeta(blockHash)._1 + 1) > lastMinedBlockHeight) | |
365 | 373 | case _ => | |
366 | 374 | true | |
367 | 375 | } | |
368 | 376 | match minerChainId(generator) { | |
369 | 377 | case currentId: Int => | |
370 | 378 | if (if ((currentId == expectedChainId)) | |
371 | 379 | then true | |
372 | 380 | else if (chainIsInactive(currentId)) | |
373 | 381 | then heightIsCorrect | |
374 | 382 | else false) | |
375 | 383 | then unit | |
376 | 384 | else throw(("miner is mining other chain " + toString(currentId))) | |
377 | 385 | case _ => | |
378 | 386 | unit | |
379 | 387 | } | |
380 | 388 | } | |
381 | 389 | ||
382 | 390 | ||
383 | 391 | func ensureCorrectEpoch (epoch) = if ((epoch == height)) | |
384 | 392 | then unit | |
385 | 393 | else throw(((("Expected block from epoch " + toString(height)) + ". Got ") + toString(epoch))) | |
386 | 394 | ||
387 | 395 | ||
388 | 396 | func addSupporter (chainId,generator) = { | |
389 | 397 | let supportersStr = getStringValue(supportersKey(chainId)) | |
390 | 398 | let supporters = split_4C(supportersStr, SEP) | |
391 | 399 | if (containsElement(supporters, toString(generator))) | |
392 | 400 | then nil | |
393 | 401 | else [StringEntry(supportersKey(chainId), ((supportersStr + SEP) + toString(generator)))] | |
394 | 402 | } | |
395 | 403 | ||
396 | 404 | ||
397 | 405 | func validateBlockHash (hexStr) = { | |
398 | 406 | let decodedBytes = fromBase16String(hexStr) | |
399 | 407 | if ((size(decodedBytes) != 32)) | |
400 | 408 | then throw("invalid block id length") | |
401 | 409 | else hexStr | |
402 | 410 | } | |
403 | 411 | ||
404 | 412 | ||
405 | 413 | func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = { | |
406 | 414 | let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1 | |
407 | 415 | let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex) | |
408 | 416 | if ((newFinalizedBlockHash == newBlockHashHex)) | |
409 | 417 | then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)] | |
410 | 418 | else if ((blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight)) | |
411 | 419 | then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)] | |
412 | 420 | else nil | |
413 | 421 | } | |
414 | 422 | ||
415 | 423 | ||
416 | 424 | @Callable(i) | |
417 | 425 | func appendBlock (blockHashHex,referenceHex) = if ((thisEpochMiner != i.originCaller)) | |
418 | 426 | then match thisEpochMiner { | |
419 | 427 | case epochMiner: Address => | |
420 | 428 | throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner))) | |
421 | 429 | case _ => | |
422 | 430 | throw("not allowed to forge blocks in this epoch, epoch miner is absent") | |
423 | 431 | } | |
424 | 432 | else { | |
425 | 433 | let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId) | |
426 | - | let $ | |
427 | - | let chainHeight = $ | |
428 | - | let lastBlockId = $ | |
434 | + | let $t01083310884 = chainMeta(chainId) | |
435 | + | let chainHeight = $t01083310884._1 | |
436 | + | let lastBlockId = $t01083310884._2 | |
429 | 437 | let checkReference = isReferenceCorrect(referenceHex, lastBlockId) | |
430 | 438 | if ((checkReference == checkReference)) | |
431 | 439 | then { | |
432 | 440 | let newChainHeight = (chainHeight + 1) | |
433 | 441 | let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes) | |
434 | 442 | let blockHash = validateBlockHash(blockHashHex) | |
435 | 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))] | |
436 | 444 | } | |
437 | 445 | else throw("Strict value is not equal to itself.") | |
438 | 446 | } | |
439 | 447 | ||
440 | 448 | ||
441 | 449 | ||
442 | 450 | @Callable(i) | |
443 | 451 | func extendMainChain (blockHashHex,referenceHex,epoch) = { | |
444 | 452 | let checkEpoch = ensureCorrectEpoch(epoch) | |
445 | 453 | if ((checkEpoch == checkEpoch)) | |
446 | 454 | then { | |
447 | 455 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
448 | 456 | if ((checkGenerator == checkGenerator)) | |
449 | 457 | then { | |
450 | 458 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit) | |
451 | 459 | if ((checkChain == checkChain)) | |
452 | 460 | then { | |
453 | 461 | let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock) | |
454 | 462 | if ((checkReference == checkReference)) | |
455 | 463 | then { | |
456 | 464 | let thisEpochMeta = match epochMeta(height) { | |
457 | 465 | case _: Unit => | |
458 | 466 | StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex)) | |
459 | 467 | case other => | |
460 | 468 | throw("Epoch already started") | |
461 | 469 | } | |
462 | 470 | let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch) | |
463 | 471 | let newChainHeight = (mainChainHeight + 1) | |
464 | 472 | let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(mainChainLastBlock)) + i.originCaller.bytes) | |
465 | 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) | |
466 | 474 | } | |
467 | 475 | else throw("Strict value is not equal to itself.") | |
468 | 476 | } | |
469 | 477 | else throw("Strict value is not equal to itself.") | |
470 | 478 | } | |
471 | 479 | else throw("Strict value is not equal to itself.") | |
472 | 480 | } | |
473 | 481 | else throw("Strict value is not equal to itself.") | |
474 | 482 | } | |
475 | 483 | ||
476 | 484 | ||
477 | 485 | ||
478 | 486 | @Callable(i) | |
479 | 487 | func startAltChain (blockHashHex,referenceHex,epoch) = { | |
480 | 488 | let checkEpoch = ensureCorrectEpoch(epoch) | |
481 | 489 | if ((checkEpoch == checkEpoch)) | |
482 | 490 | then { | |
483 | 491 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
484 | 492 | if ((checkGenerator == checkGenerator)) | |
485 | 493 | then { | |
486 | - | let $ | |
487 | - | let refChainHeight = $ | |
488 | - | let refEpoch = $ | |
489 | - | let refRef = $ | |
490 | - | let refGenerator = $ | |
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 | |
491 | 499 | let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2 | |
492 | 500 | let epochRef = if ((refEpoch >= finalizedEpoch)) | |
493 | 501 | then refEpoch | |
494 | 502 | else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized")) | |
495 | 503 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex) | |
496 | 504 | if ((checkChain == checkChain)) | |
497 | 505 | then { | |
498 | 506 | let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1) | |
499 | 507 | let referenceHeight = blockMeta(referenceHex)._1 | |
500 | 508 | let newChainHeight = (referenceHeight + 1) | |
501 | 509 | let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes) | |
502 | 510 | let thisEpochMeta = match epochMeta(height) { | |
503 | 511 | case _: Unit => | |
504 | 512 | StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex)) | |
505 | 513 | case other => | |
506 | 514 | throw("Epoch already started") | |
507 | 515 | } | |
508 | 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)] | |
509 | 517 | } | |
510 | 518 | else throw("Strict value is not equal to itself.") | |
511 | 519 | } | |
512 | 520 | else throw("Strict value is not equal to itself.") | |
513 | 521 | } | |
514 | 522 | else throw("Strict value is not equal to itself.") | |
515 | 523 | } | |
516 | 524 | ||
517 | 525 | ||
518 | 526 | ||
519 | 527 | @Callable(i) | |
520 | 528 | func extendAltChain (chainId,blockHashHex,referenceHex,epoch) = { | |
521 | 529 | let checkEpoch = ensureCorrectEpoch(epoch) | |
522 | 530 | if ((checkEpoch == checkEpoch)) | |
523 | 531 | then { | |
524 | 532 | let checkGenerator = ensureMiningEpoch(i.originCaller) | |
525 | 533 | if ((checkGenerator == checkGenerator)) | |
526 | 534 | then { | |
527 | 535 | let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._3)) | |
528 | 536 | if ((checkChain == checkChain)) | |
529 | 537 | then { | |
530 | - | let $ | |
531 | - | let chainHeight = $ | |
532 | - | let chainLastBlock = $ | |
538 | + | let $t01534015394 = chainMeta(chainId) | |
539 | + | let chainHeight = $t01534015394._1 | |
540 | + | let chainLastBlock = $t01534015394._2 | |
533 | 541 | let checkReference = isReferenceCorrect(referenceHex, chainLastBlock) | |
534 | 542 | if ((checkReference == checkReference)) | |
535 | 543 | then { | |
536 | 544 | let newChainHeight = (chainHeight + 1) | |
537 | 545 | let prevEpoch = blockMeta(referenceHex)._2 | |
538 | 546 | let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2))) | |
539 | 547 | then { | |
540 | 548 | let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch) | |
541 | 549 | ([IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (valueOrElse(getInteger(lastChainIdKey), 0) + 1))] ++ updateFinalizedBlock) | |
542 | 550 | } | |
543 | 551 | else nil | |
544 | 552 | let thisEpochMeta = match epochMeta(height) { | |
545 | 553 | case _: Unit => | |
546 | 554 | StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex)) | |
547 | 555 | case other => | |
548 | 556 | throw("Epoch already started") | |
549 | 557 | } | |
550 | 558 | let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil)) | |
551 | 559 | then (valueOrElse(minerChainId(i.originCaller), 0) != chainId) | |
552 | 560 | else false) | |
553 | 561 | then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))._1)] | |
554 | 562 | else nil | |
555 | 563 | let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes) | |
556 | 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) | |
557 | 565 | } | |
558 | 566 | else throw("Strict value is not equal to itself.") | |
559 | 567 | } | |
560 | 568 | else throw("Strict value is not equal to itself.") | |
561 | 569 | } | |
562 | 570 | else throw("Strict value is not equal to itself.") | |
563 | 571 | } | |
564 | 572 | else throw("Strict value is not equal to itself.") | |
565 | 573 | } | |
566 | 574 | ||
567 | 575 | ||
568 | 576 | ||
569 | 577 | @Callable(i) | |
570 | 578 | func join (rewardAddress) = { | |
571 | 579 | func checkRewardAddress (address) = match getBinary(minerPkKey(address)) { | |
572 | 580 | case pk: ByteVector => | |
573 | 581 | if ((pk == i.originCallerPublicKey)) | |
574 | 582 | then unit | |
575 | 583 | else throw(((("L2 miner address " + address) + " is already linked with ") + toBase58String(pk))) | |
576 | 584 | case _ => | |
577 | 585 | unit | |
578 | 586 | } | |
579 | 587 | ||
580 | 588 | if (!(isContractSetup())) | |
581 | 589 | then throw("The contract has not yet set up") | |
582 | 590 | else if ((MIN_BALANCE > wavesBalance(i.originCaller).generating)) | |
583 | 591 | then throw(((("Insufficient generating balance: " + toString(wavesBalance(i.originCaller).generating)) + ". Required: ") + toString(MIN_BALANCE))) | |
584 | 592 | else if ((size(rewardAddress) != 20)) | |
585 | 593 | then throw("rewardAddress should be an L2 address") | |
586 | 594 | else if ((size(allMiners) >= 50)) | |
587 | 595 | then throw("too many miners") | |
588 | 596 | else { | |
589 | 597 | func checkExistence (exists,miner) = if (exists) | |
590 | 598 | then true | |
591 | 599 | else (miner == toString(i.originCaller)) | |
592 | 600 | ||
593 | 601 | let alreadyExists = { | |
594 | 602 | let $l = allMiners | |
595 | 603 | let $s = size($l) | |
596 | 604 | let $acc0 = false | |
597 | 605 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
598 | 606 | then $a | |
599 | 607 | else checkExistence($a, $l[$i]) | |
600 | 608 | ||
601 | 609 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
602 | 610 | then $a | |
603 | 611 | else throw("List size exceeds 50") | |
604 | 612 | ||
605 | 613 | $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) | |
606 | 614 | } | |
607 | 615 | if (alreadyExists) | |
608 | 616 | then nil | |
609 | 617 | else { | |
610 | 618 | let newMiner = toString(i.originCaller) | |
611 | 619 | let rewardAddressHex = toBase16String(rewardAddress) | |
612 | 620 | let check = checkRewardAddress(rewardAddressHex) | |
613 | 621 | if ((check == check)) | |
614 | 622 | then { | |
615 | 623 | let newMiners = if ((size(allMiners) == 0)) | |
616 | 624 | then newMiner | |
617 | 625 | else ((allMinersStr + SEP) + newMiner) | |
618 | 626 | let deleteOldRewardAddressPk = match getString(minerRewardAddressKey(newMiner)) { | |
619 | 627 | case oldAddress: String => | |
620 | 628 | if ((oldAddress == toBase16String(rewardAddress))) | |
621 | 629 | then nil | |
622 | 630 | else [DeleteEntry(minerPkKey(oldAddress))] | |
623 | 631 | case _ => | |
624 | 632 | nil | |
625 | 633 | } | |
626 | 634 | ([StringEntry(allMinersKey, newMiners), StringEntry(minerRewardAddressKey(newMiner), ("0x" + rewardAddressHex)), BinaryEntry(minerPkKey(rewardAddressHex), i.originCallerPublicKey)] ++ deleteOldRewardAddressPk) | |
627 | 635 | } | |
628 | 636 | else throw("Strict value is not equal to itself.") | |
629 | 637 | } | |
630 | 638 | } | |
631 | 639 | } | |
632 | 640 | ||
633 | 641 | ||
634 | 642 | ||
635 | 643 | @Callable(i) | |
636 | 644 | func leave () = { | |
637 | 645 | let leavingMiner = toString(i.originCaller) | |
638 | 646 | func skipLeavingMiner (acc,miner) = if ((miner == leavingMiner)) | |
639 | 647 | then acc | |
640 | 648 | else (acc :+ miner) | |
641 | 649 | ||
642 | 650 | let remainingMiners = { | |
643 | 651 | let $l = allMiners | |
644 | 652 | let $s = size($l) | |
645 | 653 | let $acc0 = nil | |
646 | 654 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
647 | 655 | then $a | |
648 | 656 | else skipLeavingMiner($a, $l[$i]) | |
649 | 657 | ||
650 | 658 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
651 | 659 | then $a | |
652 | 660 | else throw("List size exceeds 50") | |
653 | 661 | ||
654 | 662 | $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) | |
655 | 663 | } | |
656 | 664 | let rewardAddrKey = minerRewardAddressKey(leavingMiner) | |
657 | 665 | let prevRewardAddress = valueOrErrorMessage(getString(this, rewardAddrKey), "miner has never joined") | |
658 | 666 | if ((thisEpochMiner == i.originCaller)) | |
659 | 667 | then throw("designated miner can't leave") | |
660 | 668 | else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP)), DeleteEntry(rewardAddrKey), DeleteEntry(minerPkKey(prevRewardAddress))] | |
661 | 669 | } | |
662 | 670 | ||
663 | 671 | ||
664 | 672 | ||
665 | 673 | @Callable(i) | |
666 | 674 | func setup (genesisBlockHashHex,minerReward,stakingContractAddressB58) = if (isContractSetup()) | |
667 | 675 | then throw("The contract has been already set up") | |
668 | 676 | else { | |
669 | 677 | let genesisBlockHash = fromBase16String(genesisBlockHashHex) | |
670 | 678 | let emptyPk = base58'11111111111111111111111111111111' | |
671 | 679 | let genesisMinerAddress = addressFromPublicKey(emptyPk) | |
672 | 680 | let genesisEthRewardAddress = base58'11111111111111111111' | |
673 | 681 | let genesisBlockReferenceHash = base58'11111111111111111111111111111111' | |
674 | 682 | let genesisBlockMeta = (((toBytes(0) + toBytes(height)) + genesisBlockReferenceHash) + genesisMinerAddress.bytes) | |
675 | 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)] | |
676 | 684 | } | |
677 | 685 | ||
678 | 686 |
github/deemru/w8io/c3f4982 89.72 ms ◑