tx · Eh7NKbyaoxgEJ4BwqmwtiBQho4gcdExwKQ9ZwLmSAcYj

3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch:  -0.04300000 Waves

2024.08.20 11:59 [3246951] smart account 3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch > SELF 0.00000000 Waves

{ "type": 13, "id": "Eh7NKbyaoxgEJ4BwqmwtiBQho4gcdExwKQ9ZwLmSAcYj", "fee": 4300000, "feeAssetId": null, "timestamp": 1724144418922, "version": 2, "chainId": 84, "sender": "3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch", "senderPublicKey": "3xjN6fjYDXBGUE1mcRw2Fvr4R6tEZnuJA98QFGF99sXd", "proofs": [ "3zWkSiTLgG23JszjYZkLjYmaQDS3Xm8DxV79CjhLECXM9eLCH4Wcj4m8DneGvc9nvhtsqemrZH3nL6kKxCTTkGEZ" ], "script": "base64:CAJiCAISBQoDCAgIEgYKBAgICAESBgoECAgBCBIHCgUICAEIARIGCgQICAEIEgcKBQgIAQgBEgcKBQEICAEIEggKBgEICAEIARIDCgECEgASAwoBCBIGCgQIEgEBEgYKBAgBCAhUAAdJTlRfTUFYAP//////////fwAFV0FWRVMAgMLXLwALTUlOX0JBTEFOQ0UJAGgCAKCcAQUFV0FWRVMAA1NFUAIBLAAPQkxPQ0tfSEFTSF9TSVpFACAADEFERFJFU1NfU0laRQAaABRQVUJMSUNfS0VZX0hBU0hfU0laRQAUAA5ST09UX0hBU0hfU0laRQAgABZNQVhfQ0xfVE9fRUxfVFJBTlNGRVJTABAACXplcm9lc1N0cgKACDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAEHRoaXNFcG9jaERhdGFLZXkCDXRoaXNFcG9jaERhdGEADGFsbE1pbmVyc0tleQIJYWxsTWluZXJzAA5tYWluQ2hhaW5JZEtleQILbWFpbkNoYWluSWQADmxhc3RDaGFpbklkS2V5AgtsYXN0Q2hhaW5JZAAXZmlyc3RWYWxpZEFsdENoYWluSWRLZXkCFGZpcnN0VmFsaWRBbHRDaGFpbklkAA5taW5lclJld2FyZEtleQILbWluZXJSZXdhcmQAGXN0YWtpbmdDb250cmFjdEFkZHJlc3NLZXkCFnN0YWtpbmdDb250cmFjdEFkZHJlc3MACmJsb2NrTWV0YUsCCGJsb2NrXzB4ABFmaW5hbGl6ZWRCbG9ja0tleQIOZmluYWxpemVkQmxvY2sACnRva2VuSWRLZXkCB3Rva2VuSWQAEmVsQnJpZGdlQWRkcmVzc0tleQIPZWxCcmlkZ2VBZGRyZXNzABduYXRpdmVUcmFuc2ZlcnNDb3VudEtleQIUbmF0aXZlVHJhbnNmZXJzQ291bnQAF2NsVG9FbFRyYW5zZmVyc0Vwb2NoS2V5AhRjbFRvRWxUcmFuc2ZlcnNFcG9jaAEDcGFkAQFpBAFzCQCkAwEFAWkEByRtYXRjaDAJALECAQUBcwMJAAACAAEFByRtYXRjaDAJAKwCAgIHMDAwMDAwMAUBcwMJAAACAAIFByRtYXRjaDAJAKwCAgIGMDAwMDAwBQFzAwkAAAIAAwUHJG1hdGNoMAkArAICAgUwMDAwMAUBcwMJAAACAAQFByRtYXRjaDAJAKwCAgIEMDAwMAUBcwMJAAACAAUFByRtYXRjaDAJAKwCAgIDMDAwBQFzAwkAAAIABgUHJG1hdGNoMAkArAICAgIwMAUBcwMJAAACAAcFByRtYXRjaDAJAKwCAgIBMAUBcwUBcwEXYmxvY2tFbFRvQ2xUcmFuc2ZlcnNLZXkBDGJsb2NrSGFzaEhleAkArAICAhJlbFRvQ2xUcmFuc2ZlcnNfMHgFDGJsb2NrSGFzaEhleAEMZXBvY2hNZXRhS2V5AQVlcG9jaAkArAICAgZlcG9jaF8JAQNwYWQBBQVlcG9jaAEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBB2NoYWluSWQJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgpGaXJzdEJsb2NrAQxjaGFpbk1ldGFLZXkBB2NoYWluSWQJAKwCAgIGY2hhaW5fCQEDcGFkAQUHY2hhaW5JZAESY2hhaW5MYXN0SGVpZ2h0S2V5AgdjaGFpbklkBW1pbmVyCQCsAgIJAKwCAgkArAICAgZjaGFpbl8JAQNwYWQBBQdjaGFpbklkAgFfCQClCAEFBW1pbmVyARRjaGFpbkZvcmtlZEhlaWdodEtleQEHY2hhaW5JZAkArAICCQCsAgICBmNoYWluXwkBA3BhZAEFB2NoYWluSWQCDEZvcmtlZEhlaWdodAENc3VwcG9ydGVyc0tleQEHY2hhaW5JZAkArAICCQCsAgICBWNoYWluCQCkAwEFB2NoYWluSWQCClN1cHBvcnRlcnMBFW1pbmVyUmV3YXJkQWRkcmVzc0tleQEJbWluZXJBZGRyCQCsAgIJAKwCAgIGbWluZXJfBQltaW5lckFkZHICDl9SZXdhcmRBZGRyZXNzAQptaW5lclBrS2V5AQ1yZXdhcmRBZGRyZXNzCQCsAgIJAKwCAgIIbWluZXJfMHgFDXJld2FyZEFkZHJlc3MCA19QSwEPbWluZXJDaGFpbklkS2V5AQVtaW5lcgkArAICCQCsAgICBm1pbmVyXwkApQgBBQVtaW5lcgIIX0NoYWluSWQAFG5hdGl2ZVRyYW5zZmVyc0NvdW50CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFF25hdGl2ZVRyYW5zZmVyc0NvdW50S2V5AAABEW5hdGl2ZVRyYW5zZmVyS2V5AQVpbmRleAkArAICAg9uYXRpdmVUcmFuc2Zlcl8JAKQDAQUFaW5kZXgBFW1rTmF0aXZlVHJhbnNmZXJFbnRyeQMFaW5kZXgQZGVzdEVsQWRkcmVzc0hleAZhbW91bnQJAQtTdHJpbmdFbnRyeQIJARFuYXRpdmVUcmFuc2ZlcktleQEFBWluZGV4CQCsAgIJAKwCAgkArAICAgIweAUQZGVzdEVsQWRkcmVzc0hleAUDU0VQCQCkAwEFBmFtb3VudAAUY2xUb0VsVHJhbnNmZXJzRXBvY2gJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUXY2xUb0VsVHJhbnNmZXJzRXBvY2hLZXkFB0lOVF9NQVgBHnJlcXVpcmVDbFRvRWxUcmFuc2ZlcnNEaXNhYmxlZAADCQBmAgUUY2xUb0VsVHJhbnNmZXJzRXBvY2gFBmhlaWdodAUEdW5pdAkAAgEJAKwCAgkArAICAidDTCB0byBFTCB0cmFuc2ZlcnMgYWN0aXZhdGVkIG9uIGVwb2NoICMJAKQDAQUGaGVpZ2h0AhUuIFVwZ3JhZGUgeW91ciBjbGllbnQBHXJlcXVpcmVDbFRvRWxUcmFuc2ZlcnNFbmFibGVkAAMJAGcCBQZoZWlnaHQFFGNsVG9FbFRyYW5zZmVyc0Vwb2NoBQR1bml0CQACAQkArAICCQCsAgIJAKwCAgIvQ0wgdG8gRUwgdHJhbnNmZXJzIGhhdmVuJ3QgYWN0aXZhdGVkIG9uIGVwb2NoICMJAKQDAQUGaGVpZ2h0AhouIFdhaXQgZm9yIGFjdGl2YXRpb24gb24gIwkApAMBBRRjbFRvRWxUcmFuc2ZlcnNFcG9jaAEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMQcmVmVHJhbnNmZXJJbmRleA10cmFuc2ZlckluZGV4DGV4cGVjdFJld2FyZAQMbWF4VHJhbnNmZXJzAwUMZXhwZWN0UmV3YXJkCQBlAgUWTUFYX0NMX1RPX0VMX1RSQU5TRkVSUwABBRZNQVhfQ0xfVE9fRUxfVFJBTlNGRVJTBA9hY3R1YWxUcmFuc2ZlcnMJAGUCBQ10cmFuc2ZlckluZGV4BRByZWZUcmFuc2ZlckluZGV4BAtjaGVja051bWJlcgMJAGYCBQ9hY3R1YWxUcmFuc2ZlcnMFDG1heFRyYW5zZmVycwkAAgEJAKwCAgkArAICCQCsAgICDUFsbG93ZWQgb25seSAJAKQDAQUMbWF4VHJhbnNmZXJzAhAgdHJhbnNmZXJzLCBnb3QgCQCkAwEFD2FjdHVhbFRyYW5zZmVycwYDCQAAAgULY2hlY2tOdW1iZXIFC2NoZWNrTnVtYmVyAwkAZwIFDXRyYW5zZmVySW5kZXgFFG5hdGl2ZVRyYW5zZmVyc0NvdW50CQACAQkArAICCQCsAgIJAKwCAgIVQXR0ZW1wdCB0byB0cmFuc2ZlciAjCQCkAwEFDXRyYW5zZmVySW5kZXgCFy4gQXZhaWxhYmxlIHRyYW5zZmVyczogCQCkAwEFFG5hdGl2ZVRyYW5zZmVyc0NvdW50BgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEKYW1vdW50R3RFcQMBdARndEVxCXF1ZXVlU2l6ZQMJAGcCCAUBdAZhbW91bnQFBGd0RXEGCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIUVHJhbnNmZXJyaW5nIGFtb3VudCAJAKQDAQgFAXQGYW1vdW50Ag4gc2hvdWxkIGJlID49IAkApAMBBQRndEVxAhMgZm9yIHF1ZXVlIHNpemUgb2YgCQCkAwEFCXF1ZXVlU2l6ZQIXLiBUcmFuc2ZlciBtb3JlIG9yIHdhaXQAFnN0YWtpbmdDb250cmFjdEFkZHJlc3MEByRtYXRjaDAJAJ0IAgUEdGhpcwUZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0tleQMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBBQFzCQCsAgICImludmFsaWQgc3Rha2luZyBjb250cmFjdCBhZGRyZXNzOiAFAXMJAQdBZGRyZXNzAQkBEUBleHRyTmF0aXZlKDEwNTIpAgUEdGhpcwUZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0tleQERZ2VuZXJhdGluZ0JhbGFuY2UBB2FkZHJlc3MEByRtYXRjaDAJAJ0IAgUWc3Rha2luZ0NvbnRyYWN0QWRkcmVzcwkArAICAgQlc19fCQClCAEFB2FkZHJlc3MDCQABAgUHJG1hdGNoMAIGU3RyaW5nBANzdHIFByRtYXRjaDAECXBhcmFtTGlzdAkAtQkCBQNzdHICAl9fBApwcmV2SGVpZ2h0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJcGFyYW1MaXN0AAEEC3ByZXZCYWxhbmNlCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJcGFyYW1MaXN0AAIECm5leHRIZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlwYXJhbUxpc3QAAwQLbmV4dEJhbGFuY2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlwYXJhbUxpc3QABAMJAGcCBQZoZWlnaHQFCm5leHRIZWlnaHQFC25leHRCYWxhbmNlAwkAZwIFBmhlaWdodAUKcHJldkhlaWdodAULcHJldkJhbGFuY2UAAAAAAQljaGFpbk1ldGEBB2NoYWluSWQEAXMJARFAZXh0ck5hdGl2ZSgxMDU4KQEJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkBAVpdGVtcwkAtQkCBQFzBQNTRVAJAJQKAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWl0ZW1zAAAJAJEDAgUFaXRlbXMAAQEQbWtDaGFpbk1ldGFFbnRyeQMHY2hhaW5JZA5uZXdDaGFpbkhlaWdodAxibG9ja0hhc2hIZXgJAQtTdHJpbmdFbnRyeQIJAQxjaGFpbk1ldGFLZXkBBQdjaGFpbklkCQCsAgIJAKwCAgkApAMBBQ5uZXdDaGFpbkhlaWdodAUDU0VQBQxibG9ja0hhc2hIZXgAC21haW5DaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDm1haW5DaGFpbklkS2V5AAAACyR0MDY0MjM2NDg5CQEJY2hhaW5NZXRhAQULbWFpbkNoYWluSWQAD21haW5DaGFpbkhlaWdodAgFCyR0MDY0MjM2NDg5Al8xABJtYWluQ2hhaW5MYXN0QmxvY2sIBQskdDA2NDIzNjQ4OQJfMgEJZXBvY2hNZXRhAQVlcG9jaAQHJG1hdGNoMAkAoggBCQEMZXBvY2hNZXRhS2V5AQUFZXBvY2gDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBAlmcmFnbWVudHMJALUJAgUBcwUDU0VQCQCVCgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAJEDAgUJZnJhZ21lbnRzAAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmcmFnbWVudHMAAQkAkQMCBQlmcmFnbWVudHMAAgUEdW5pdAALJHQwNjcyMDcxODQEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIWKEFkZHJlc3MsIEludCwgU3RyaW5nKQQBbQUHJG1hdGNoMAUBbQQHJG1hdGNoMQkAoggBBRB0aGlzRXBvY2hEYXRhS2V5AwkAAQIFByRtYXRjaDECBlN0cmluZwQQcmF3VGhpc0Vwb2NoRGF0YQUHJG1hdGNoMQQNdGhpc0Vwb2NoRGF0YQkAtQkCBRByYXdUaGlzRXBvY2hEYXRhBQNTRVAECXRoaXNFcG9jaAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDXRoaXNFcG9jaERhdGEAAAkAlQoDAwkAAAIFCXRoaXNFcG9jaAUGaGVpZ2h0CQERQGV4dHJOYXRpdmUoMTA2MikBCQCRAwIFDXRoaXNFcG9jaERhdGEAAQUEdW5pdAAAAgAJAJUKAwUEdW5pdAAAAgAADnRoaXNFcG9jaE1pbmVyCAULJHQwNjcyMDcxODQCXzEADHRoaXNFcG9jaFJlZggFCyR0MDY3MjA3MTg0Al8yABJ0aGlzRXBvY2hMYXN0QmxvY2sIBQskdDA2NzIwNzE4NAJfMwAMYWxsTWluZXJzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFDGFsbE1pbmVyc0tleQIAAAlhbGxNaW5lcnMEByRtYXRjaDAFDGFsbE1pbmVyc1N0cgMJAAACAgAFByRtYXRjaDAFA25pbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcEA3JhdwUHJG1hdGNoMAkAvAkCBQNyYXcFA1NFUAkAAgECC01hdGNoIGVycm9yAQlibG9ja01ldGEBB2Jsb2NrSWQEBG1ldGEJARFAZXh0ck5hdGl2ZSgxMDU3KQEJAKwCAgUKYmxvY2tNZXRhSwUHYmxvY2tJZAQIbWV0YVNpemUJAMgBAQUEbWV0YQQLYmxvY2tIZWlnaHQJALEJAQUEbWV0YQQKYmxvY2tFcG9jaAkAsgkCBQRtZXRhAAgEC2Jsb2NrUGFyZW50CQDJAQIJAMoBAgUEbWV0YQAQBQ9CTE9DS19IQVNIX1NJWkUEDmJsb2NrR2VuZXJhdG9yCQDJAQIJAMoBAgUEbWV0YQkAZAIAEAUPQkxPQ0tfSEFTSF9TSVpFBQxBRERSRVNTX1NJWkUEB2NoYWluSWQJALIJAgUEbWV0YQkAZAIJAGQCABAFD0JMT0NLX0hBU0hfU0laRQUMQUREUkVTU19TSVpFBApiYXNlT2Zmc2V0CQBkAgkAZAIAGAUPQkxPQ0tfSEFTSF9TSVpFBQxBRERSRVNTX1NJWkUEDnJlbWFpbmluZ0J5dGVzCQBlAgUIbWV0YVNpemUFCmJhc2VPZmZzZXQEF2VsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoAwkAZwIFDnJlbWFpbmluZ0J5dGVzBQ5ST09UX0hBU0hfU0laRQkAyQECCQDKAQIFBG1ldGEFCmJhc2VPZmZzZXQFDlJPT1RfSEFTSF9TSVpFAQAEF2xhc3RDbFRvRWxUcmFuc2ZlckluZGV4AwMJAAACBQ5yZW1haW5pbmdCeXRlcwAIBgkAZgIFDnJlbWFpbmluZ0J5dGVzBQ5ST09UX0hBU0hfU0laRQkAsgkCBQRtZXRhCQBkAgUKYmFzZU9mZnNldAkAyAEBBRdlbFRvQ2xUcmFuc2ZlcnNSb290SGFzaAD///////////8BCQCZCgcFC2Jsb2NrSGVpZ2h0BQpibG9ja0Vwb2NoBQtibG9ja1BhcmVudAUOYmxvY2tHZW5lcmF0b3IFB2NoYWluSWQFF2VsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoBRdsYXN0Q2xUb0VsVHJhbnNmZXJJbmRleAEQbWtCbG9ja01ldGFFbnRyeQcMYmxvY2tIYXNoSGV4C2Jsb2NrSGVpZ2h0DmJsb2NrUGFyZW50SGV4DmJsb2NrR2VuZXJhdG9yB2NoYWluSWQaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgED2Jsb2NrRXBvY2hCeXRlcwkAmgMBBQZoZWlnaHQED2Jsb2NrTWV0YUJ5dGVzMQkAywECCQDLAQIJAMsBAgkAywECCQDLAQIJAJoDAQULYmxvY2tIZWlnaHQFD2Jsb2NrRXBvY2hCeXRlcwkA3QQBBQ5ibG9ja1BhcmVudEhleAgFDmJsb2NrR2VuZXJhdG9yBWJ5dGVzCQCaAwEFB2NoYWluSWQJAN0EAQUaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgED2Jsb2NrTWV0YUJ5dGVzMgMJAGYCBRRjbFRvRWxUcmFuc2ZlcnNFcG9jaAUGaGVpZ2h0AQAJAJoDAQUXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgJAQtCaW5hcnlFbnRyeQIJAKwCAgUKYmxvY2tNZXRhSwUMYmxvY2tIYXNoSGV4CQDLAQIFD2Jsb2NrTWV0YUJ5dGVzMQUPYmxvY2tNZXRhQnl0ZXMyAQxsYXN0SGVpZ2h0QnkCBW1pbmVyB2NoYWluSWQEByRtYXRjaDAJAJ8IAQkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQFBW1pbmVyAwkAAQIFByRtYXRjaDACA0ludAQBaAUHJG1hdGNoMAUBaAQJYmxvY2tIYXNoCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIJAKwCAgkArAICAgVjaGFpbgkApAMBBQdjaGFpbklkAgtMYXN0TWluZWRCeQkApQgBBQVtaW5lcggJAQlibG9ja01ldGEBBQlibG9ja0hhc2gCXzEADCR0MDkyNDYxMDIxMgQJaGl0U291cmNlBAckbWF0Y2gwCAUJbGFzdEJsb2NrA3ZyZgMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAN2cmYFByRtYXRjaDAFA3ZyZggFCWxhc3RCbG9jaxNnZW5lcmF0aW9uU2lnbmF0dXJlCgEMcHJvY2Vzc01pbmVyAgRwcmV2BW1pbmVyBAskdDA5NTQ0OTYwNwUEcHJldgQJcHJldkRlbGF5CAULJHQwOTU0NDk2MDcCXzEECXByZXZNaW5lcggFCyR0MDk1NDQ5NjA3Al8yBBBwcmV2VG90YWxCYWxhbmNlCAULJHQwOTU0NDk2MDcCXzMECnByZXZNaW5lcnMIBQskdDA5NTQ0OTYwNwJfNAQMbWluZXJBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA2MikBBQVtaW5lcgQPd2F2ZXNHZW5CYWxhbmNlCAkA7wcBBQxtaW5lckFkZHJlc3MKZ2VuZXJhdGluZwQMbWluZXJCYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQxtaW5lckFkZHJlc3MDAwkAZgIFC01JTl9CQUxBTkNFBQ93YXZlc0dlbkJhbGFuY2UGCQBnAgAABQxtaW5lckJhbGFuY2UFBHByZXYECW5leHREZWxheQkAhQcCBQxtaW5lckFkZHJlc3MFDG1pbmVyQmFsYW5jZQMJAGYCBQlwcmV2RGVsYXkFCW5leHREZWxheQkAlgoEBQluZXh0RGVsYXkFBW1pbmVyCQBkAgUQcHJldlRvdGFsQmFsYW5jZQUMbWluZXJCYWxhbmNlCQDNCAIFCnByZXZNaW5lcnMFBW1pbmVyCQCWCgQFCXByZXZEZWxheQUJcHJldk1pbmVyCQBkAgUQcHJldlRvdGFsQmFsYW5jZQUMbWluZXJCYWxhbmNlCQDNCAIFCnByZXZNaW5lcnMFBW1pbmVyCgACJGwFCWFsbE1pbmVycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJYKBAUHSU5UX01BWAIAAAAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEMcHJvY2Vzc01pbmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIADWNvbXB1dGVkRGVsYXkIBQwkdDA5MjQ2MTAyMTICXzEAEWNvbXB1dGVkR2VuZXJhdG9yCAUMJHQwOTI0NjEwMjEyAl8yABRjb21wdXRlZFRvdGFsQmFsYW5jZQgFDCR0MDkyNDYxMDIxMgJfMwAOZmlsdGVyZWRNaW5lcnMIBQwkdDA5MjQ2MTAyMTICXzQBE2dldENoYWluTGFzdEJsb2NrSWQBB2NoYWluSWQICQEJY2hhaW5NZXRhAQUHY2hhaW5JZAJfMgANJHQwMTAyNzgxMDM4NQkBCWJsb2NrTWV0YQEFEm1haW5DaGFpbkxhc3RCbG9jawAMbWNsYklnbm9yZWQxCAUNJHQwMTAyNzgxMDM4NQJfMQAObWFpbkNoYWluRXBvY2gIBQ0kdDAxMDI3ODEwMzg1Al8yABNtYWluQ2hhaW5QYXJlbnRIYXNoCAUNJHQwMTAyNzgxMDM4NQJfMwASbWFpbkNoYWluR2VuZXJhdG9yCAUNJHQwMTAyNzgxMDM4NQJfNAEbY2FsY3VsYXRlRmluYWxpemVkQmxvY2tIYXNoAwhjdXJNaW5lcgxjdXJQcmV2RXBvY2gQY3VyTGFzdEJsb2NrSGFzaAQLb2Zmc2V0c18xMDAJALwJAgJkOjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6OgIABAtoYWxmQmFsYW5jZQkAaQIFFGNvbXB1dGVkVG90YWxCYWxhbmNlAAIKAQRzdGVwAgRwcmV2BG5leHQEDSR0MDEwNzUxMTA4MTUFBHByZXYECXRoaXNFcG9jaAgFDSR0MDEwNzUxMTA4MTUCXzEEDHRvdGFsQmFsYW5jZQgFDSR0MDEwNzUxMTA4MTUCXzIEDm1heWJlU2FmZUVwb2NoCAUNJHQwMTA3NTExMDgxNQJfMwQKcHJldk1pbmVycwgFDSR0MDEwNzUxMTA4MTUCXzQEByRtYXRjaDAFDm1heWJlU2FmZUVwb2NoAwkAAQIFByRtYXRjaDACBFVuaXQEDSR0MDEwODczMTEwMzkDCQAAAgUJdGhpc0Vwb2NoBQZoZWlnaHQJAJUKAwUIY3VyTWluZXIFDGN1clByZXZFcG9jaAUQY3VyTGFzdEJsb2NrSGFzaAkBBXZhbHVlAQkBCWVwb2NoTWV0YQEFCXRoaXNFcG9jaAQFbWluZXIIBQ0kdDAxMDg3MzExMDM5Al8xBAlwcmV2RXBvY2gIBQ0kdDAxMDg3MzExMDM5Al8yBA1sYXN0QmxvY2tIYXNoCAUNJHQwMTA4NzMxMTAzOQJfMwMJAAACBQlwcmV2RXBvY2gAAAkAlgoEBQl0aGlzRXBvY2gFDHRvdGFsQmFsYW5jZQUNbGFzdEJsb2NrSGFzaAUJYWxsTWluZXJzBA0kdDAxMTE2NDExMzY2AwkBD2NvbnRhaW5zRWxlbWVudAIFCnByZXZNaW5lcnMFBW1pbmVyCQCUCgIFDHRvdGFsQmFsYW5jZQUKcHJldk1pbmVycwkAlAoCCQBkAgUMdG90YWxCYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQVtaW5lcgkAzAgCBQVtaW5lcgUKcHJldk1pbmVycwQPbmV3VG90YWxCYWxhbmNlCAUNJHQwMTExNjQxMTM2NgJfMQQJbmV3TWluZXJzCAUNJHQwMTExNjQxMTM2NgJfMgMJAGYCBQ9uZXdUb3RhbEJhbGFuY2UFC2hhbGZCYWxhbmNlCQCWCgQFCXRoaXNFcG9jaAUPbmV3VG90YWxCYWxhbmNlBQ1sYXN0QmxvY2tIYXNoBQlhbGxNaW5lcnMJAJYKBAUJcHJldkVwb2NoBQ9uZXdUb3RhbEJhbGFuY2UFBHVuaXQFCW5ld01pbmVycwUEcHJldgQNJHQwMTE1OTkxMTczMgoAAiRsCQDOCAIFC29mZnNldHNfMTAwBQtvZmZzZXRzXzEwMAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJYKBAUGaGVpZ2h0AAAFBHVuaXQFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEc3RlcAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIVTGlzdCBzaXplIGV4Y2VlZHMgMjAwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgAzADQANQA2ADcAOAA5ADoAOwA8AD0APgA/AEAAQQBCAEMARABFAEYARwBIAEkASgBLAEwATQBOAE8AUABRAFIAUwBUAFUAVgBXAFgAWQBaAFsAXABdAF4AXwBgAGEAYgBjAGQAZQBmAGcAaABpAGoAawBsAG0AbgBvAHAAcQByAHMAdAB1AHYAdwB4AHkAegB7AHwAfQB+AH8AgAEAgQEAggEAgwEAhAEAhQEAhgEAhwEAiAEAiQEAigEAiwEAjAEAjQEAjgEAjwEAkAEAkQEAkgEAkwEAlAEAlQEAlgEAlwEAmAEAmQEAmgEAmwEAnAEAnQEAngEAnwEAoAEAoQEAogEAowEApAEApQEApgEApwEAqAEAqQEAqgEAqwEArAEArQEArgEArwEAsAEAsQEAsgEAswEAtAEAtQEAtgEAtwEAuAEAuQEAugEAuwEAvAEAvQEAvgEAvwEAwAEAwQEAwgEAwwEAxAEAxQEAxgEAxwEAyAEEDWZhbGxiYWNrRXBvY2gIBQ0kdDAxMTU5OTExNzMyAl8xBAx0b3RhbEJhbGFuY2UIBQ0kdDAxMTU5OTExNzMyAl8yBBVmaW5hbGl6ZWRCbG9ja0hhc2hPcHQIBQ0kdDAxMTU5OTExNzMyAl8zBAZtaW5lcnMIBQ0kdDAxMTU5OTExNzMyAl80BAckbWF0Y2gwBRVmaW5hbGl6ZWRCbG9ja0hhc2hPcHQDCQABAgUHJG1hdGNoMAIGU3RyaW5nBBJmaW5hbGl6ZWRCbG9ja0hhc2gFByRtYXRjaDAFEmZpbmFsaXplZEJsb2NrSGFzaAgJAQV2YWx1ZQEJAQllcG9jaE1ldGEBBQ1mYWxsYmFja0Vwb2NoAl8zARFzdXBwb3J0aW5nQmFsYW5jZQEHY2hhaW5JZAoBCmFkZEJhbGFuY2UCA2FjYwxnZW5lcmF0b3JTdHIEDSR0MDEyMDAyMTIwMzgFA2FjYwQMdG90YWxCYWxhbmNlCAUNJHQwMTIwMDIxMjAzOAJfMQQKZ2VuZXJhdG9ycwgFDSR0MDEyMDAyMTIwMzgCXzIECWdlbmVyYXRvcgkBEUBleHRyTmF0aXZlKDEwNjIpAQUMZ2VuZXJhdG9yU3RyAwkBD2NvbnRhaW5zRWxlbWVudAIFCmdlbmVyYXRvcnMFCWdlbmVyYXRvcgUDYWNjBAdiYWxhbmNlCQERZ2VuZXJhdGluZ0JhbGFuY2UBBQlnZW5lcmF0b3IJAJQKAgkAZAIFDHRvdGFsQmFsYW5jZQUHYmFsYW5jZQkAzQgCBQpnZW5lcmF0b3JzBQlnZW5lcmF0b3IEDWFsbEdlbmVyYXRvcnMJALwJAgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBDXN1cHBvcnRlcnNLZXkBBQdjaGFpbklkBQNTRVAEDSR0MDEyMzYwMTI0MjUKAAIkbAUNYWxsR2VuZXJhdG9ycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAABQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCmFkZEJhbGFuY2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFUxpc3Qgc2l6ZSBleGNlZWRzIDEwMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAGIAYwBkBAdiYWxhbmNlCAUNJHQwMTIzNjAxMjQyNQJfMQQCX2cIBQ0kdDAxMjM2MDEyNDI1Al8yBQdiYWxhbmNlAQ9pc0NvbnRyYWN0U2V0dXAACQEJaXNEZWZpbmVkAQkAnwgBBQ5taW5lclJld2FyZEtleQERZW5zdXJlTWluaW5nRXBvY2gBCWdlbmVyYXRvcgMJAQIhPQIJAKUIAQUJZ2VuZXJhdG9yBRFjb21wdXRlZEdlbmVyYXRvcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkA2AQBCAUJZ2VuZXJhdG9yBWJ5dGVzAhsgaXMgbm90IGFsbG93ZWQgdG8gbWluZSBpbiAJAKQDAQUGaGVpZ2h0AhEgZXBvY2guIEV4cGVjdGVkIAURY29tcHV0ZWRHZW5lcmF0b3IFBHVuaXQBEmlzUmVmZXJlbmNlQ29ycmVjdAIJcmVmZXJlbmNlCWxhc3RCbG9jawMJAAACBQlyZWZlcmVuY2UFCWxhc3RCbG9jawUEdW5pdAkAAgEJAKwCAgkArAICCQCsAgICMEV4cGVjdGVkIGEgcmVmZXJlbmNlIHRvIHRoZSBjaGFpbiBsYXN0IGJsb2NrOiAweAUJbGFzdEJsb2NrAgkuIEdvdDogMHgFCXJlZmVyZW5jZQEPY2hhaW5Jc0luYWN0aXZlAQdjaGFpbklkBAxmaXJzdEJsb2NrSWQJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEFB2NoYWluSWQEFGZpcnN0VmFsaWRBbHRDaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5AAADCQBmAgUUZmlyc3RWYWxpZEFsdENoYWluSWQFB2NoYWluSWQGCQBmAggJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMQgJAQlibG9ja01ldGEBBQxmaXJzdEJsb2NrSWQCXzEBDG1pbmVyQ2hhaW5JZAEFbWluZXIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBD21pbmVyQ2hhaW5JZEtleQEFBW1pbmVyCQCfCAEJAKwCAgIJY2hhaW5JZE9mCQClCAEFBW1pbmVyAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMJZ2VuZXJhdG9yD2V4cGVjdGVkQ2hhaW5JZBBjaGVja0hlaWdodEJsb2NrBA9oZWlnaHRJc0NvcnJlY3QEByRtYXRjaDAFEGNoZWNrSGVpZ2h0QmxvY2sDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAlibG9ja0hhc2gFByRtYXRjaDAEFGxhc3RNaW5lZEJsb2NrSGVpZ2h0CQEMbGFzdEhlaWdodEJ5AgUJZ2VuZXJhdG9yBQttYWluQ2hhaW5JZAkAZgIJAGQCCAkBCWJsb2NrTWV0YQEFCWJsb2NrSGFzaAJfMQABBRRsYXN0TWluZWRCbG9ja0hlaWdodAYEByRtYXRjaDAJAQxtaW5lckNoYWluSWQBBQlnZW5lcmF0b3IDCQABAgUHJG1hdGNoMAIDSW50BAljdXJyZW50SWQFByRtYXRjaDADAwkAAAIFCWN1cnJlbnRJZAUPZXhwZWN0ZWRDaGFpbklkBgMJAQ9jaGFpbklzSW5hY3RpdmUBBQljdXJyZW50SWQFD2hlaWdodElzQ29ycmVjdAcFBHVuaXQJAAIBCQCsAgICHG1pbmVyIGlzIG1pbmluZyBvdGhlciBjaGFpbiAJAKQDAQUJY3VycmVudElkBQR1bml0ARJlbnN1cmVDb3JyZWN0RXBvY2gBBWVwb2NoAwkAAAIFBWVwb2NoBQZoZWlnaHQFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAhpFeHBlY3RlZCBibG9jayBmcm9tIGVwb2NoIAkApAMBBQZoZWlnaHQCBi4gR290IAkApAMBBQVlcG9jaAEMYWRkU3VwcG9ydGVyAgdjaGFpbklkCWdlbmVyYXRvcgQNc3VwcG9ydGVyc1N0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBDXN1cHBvcnRlcnNLZXkBBQdjaGFpbklkBApzdXBwb3J0ZXJzCQC8CQIFDXN1cHBvcnRlcnNTdHIFA1NFUAMJAQ9jb250YWluc0VsZW1lbnQCBQpzdXBwb3J0ZXJzCQClCAEFCWdlbmVyYXRvcgUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1zdXBwb3J0ZXJzS2V5AQUHY2hhaW5JZAkArAICCQCsAgIFDXN1cHBvcnRlcnNTdHIFA1NFUAkApQgBBQlnZW5lcmF0b3IFA25pbAEJc2V0T3JGYWlsAgVmbGFncwVpbmRleAMJAGYCAAAFBWluZGV4CQACAQkArAICAiJDYW4ndCB3aXRoZHJhdyBhdCBuZWdhdGl2ZSBpbmRleDogCQCkAwEFBWluZGV4BAlmbGFnc1NpemUJALECAQUFZmxhZ3MDCQBnAgUFaW5kZXgFCWZsYWdzU2l6ZQQJYWRkWmVyb2VzCQBlAgUFaW5kZXgFCWZsYWdzU2l6ZQMJAGYCBQlhZGRaZXJvZXMJALECAQUJemVyb2VzU3RyCQACAQkArAICCQCsAgICCkNhbid0IGFkZCAJAKQDAQUJYWRkWmVyb2VzAiUgZW1wdHkgZmxhZ3MuIENvbnRhY3Qgd2l0aCBkZXZlbG9wZXJzCQCsAgIJAKwCAgUFZmxhZ3MJAK8CAgUJemVyb2VzU3RyBQlhZGRaZXJvZXMCATEEBHRhaWwJALACAgUFZmxhZ3MFBWluZGV4BAdhdEluZGV4CQCvAgIFBHRhaWwAAQMJAAACBQdhdEluZGV4AgEwCQCsAgIJAKwCAgkArwICBQVmbGFncwUFaW5kZXgCATEJALACAgUEdGFpbAABCQACAQkArAICCQCsAgICClRyYW5zZmVyICMJAKQDAQUFaW5kZXgCFyBoYXMgYmVlbiBhbHJlYWR5IHRha2VuARF2YWxpZGF0ZUJsb2NrSGFzaAEGaGV4U3RyBAxkZWNvZGVkQnl0ZXMJAN0EAQUGaGV4U3RyAwkBAiE9AgkAyAEBBQxkZWNvZGVkQnl0ZXMAIAkAAgECF2ludmFsaWQgYmxvY2sgaWQgbGVuZ3RoBQZoZXhTdHIBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwZjYWxsZXIPbmV3QmxvY2tIYXNoSGV4CXByZXZFcG9jaAQXY3VyRmluYWxpemVkQmxvY2tIZWlnaHQICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkCXzEEFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAkBG2NhbGN1bGF0ZUZpbmFsaXplZEJsb2NrSGFzaAMFBmNhbGxlcgUJcHJldkVwb2NoBQ9uZXdCbG9ja0hhc2hIZXgDAwkAAAIFFW5ld0ZpbmFsaXplZEJsb2NrSGFzaAUPbmV3QmxvY2tIYXNoSGV4BgkAZgIICQEJYmxvY2tNZXRhAQUVbmV3RmluYWxpemVkQmxvY2tIYXNoAl8xBRdjdXJGaW5hbGl6ZWRCbG9ja0hlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCBRFmaW5hbGl6ZWRCbG9ja0tleQUVbmV3RmluYWxpemVkQmxvY2tIYXNoBQNuaWwFA25pbA0BaQEOYXBwZW5kQmxvY2tfdjIDDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgEC2NoZWNrQ2xUb0VsCQEecmVxdWlyZUNsVG9FbFRyYW5zZmVyc0Rpc2FibGVkAAMJAAACBQtjaGVja0NsVG9FbAULY2hlY2tDbFRvRWwDCQECIT0CBQ50aGlzRXBvY2hNaW5lcggFAWkMb3JpZ2luQ2FsbGVyBAckbWF0Y2gwBQ50aGlzRXBvY2hNaW5lcgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAplcG9jaE1pbmVyBQckbWF0Y2gwCQACAQkArAICAjlub3QgYWxsb3dlZCB0byBmb3JnZSBibG9ja3MgaW4gdGhpcyBlcG9jaCwgZXhwZWN0ZWQgZnJvbSAJAKUIAQUKZXBvY2hNaW5lcgkAAgECQG5vdCBhbGxvd2VkIHRvIGZvcmdlIGJsb2NrcyBpbiB0aGlzIGVwb2NoLCBlcG9jaCBtaW5lciBpcyBhYnNlbnQEB2NoYWluSWQJAQt2YWx1ZU9yRWxzZQIJAQxtaW5lckNoYWluSWQBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBA0kdDAxNjU4MjE2NjMzCQEJY2hhaW5NZXRhAQUHY2hhaW5JZAQLY2hhaW5IZWlnaHQIBQ0kdDAxNjU4MjE2NjMzAl8xBAtsYXN0QmxvY2tJZAgFDSR0MDE2NTgyMTY2MzMCXzIEDmNoZWNrUmVmZXJlbmNlCQESaXNSZWZlcmVuY2VDb3JyZWN0AgUMcmVmZXJlbmNlSGV4BQtsYXN0QmxvY2tJZAMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDm5ld0NoYWluSGVpZ2h0CQBkAgULY2hhaW5IZWlnaHQAAQQOY2hlY2tCbG9ja0hhc2gJARF2YWxpZGF0ZUJsb2NrSGFzaAEFDGJsb2NrSGFzaEhleAMJAAACBQ5jaGVja0Jsb2NrSGFzaAUOY2hlY2tCbG9ja0hhc2gJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkHBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BQtsYXN0QmxvY2tJZAgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAD///////////8BCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCCQEQbWtDaGFpbk1ldGFFbnRyeQMFB2NoYWluSWQFDm5ld0NoYWluSGVpZ2h0BQxibG9ja0hhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKwCAgkArAICCQClCAEJAQV2YWx1ZQEFDnRoaXNFcG9jaE1pbmVyBQNTRVAJAKQDAQUMdGhpc0Vwb2NoUmVmBQNTRVAFDGJsb2NrSGFzaEhleAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDmFwcGVuZEJsb2NrX3YzBAxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4GmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4F2xhc3RDbFRvRWxUcmFuc2ZlckluZGV4BAtjaGVja0VsVG9DbAkBHXJlcXVpcmVDbFRvRWxUcmFuc2ZlcnNFbmFibGVkAAMJAAACBQtjaGVja0VsVG9DbAULY2hlY2tFbFRvQ2wEC2NoZWNrQ2FsbGVyAwkAAAIFDnRoaXNFcG9jaE1pbmVyCAUBaQxvcmlnaW5DYWxsZXIGBAckbWF0Y2gwBQ50aGlzRXBvY2hNaW5lcgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAplcG9jaE1pbmVyBQckbWF0Y2gwCQACAQkArAICAjlub3QgYWxsb3dlZCB0byBmb3JnZSBibG9ja3MgaW4gdGhpcyBlcG9jaCwgZXhwZWN0ZWQgZnJvbSAJAKUIAQUKZXBvY2hNaW5lcgkAAgECQG5vdCBhbGxvd2VkIHRvIGZvcmdlIGJsb2NrcyBpbiB0aGlzIGVwb2NoLCBlcG9jaCBtaW5lciBpcyBhYnNlbnQDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBAdjaGFpbklkCQELdmFsdWVPckVsc2UCCQEMbWluZXJDaGFpbklkAQgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAQNJHQwMTc4NjAxNzkxMQkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMTc4NjAxNzkxMQJfMQQLbGFzdEJsb2NrSWQIBQ0kdDAxNzg2MDE3OTExAl8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAULbGFzdEJsb2NrSWQDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5jaGVja1RyYW5zZmVycwkBFmVuc3VyZUNvcnJlY3RUcmFuc2ZlcnMDCAkBCWJsb2NrTWV0YQEFDHJlZmVyZW5jZUhleAJfNwUXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgHAwkAAAIFDmNoZWNrVHJhbnNmZXJzBQ5jaGVja1RyYW5zZmVycwQObmV3Q2hhaW5IZWlnaHQJAGQCBQtjaGFpbkhlaWdodAABBA5jaGVja0Jsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4AwkAAAIFDmNoZWNrQmxvY2tIYXNoBQ5jaGVja0Jsb2NrSGFzaAkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQcFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFC2xhc3RCbG9ja0lkCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQFGmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4BRdsYXN0Q2xUb0VsVHJhbnNmZXJJbmRleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFB2NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQdjaGFpbklkBQ5uZXdDaGFpbkhlaWdodAUMYmxvY2tIYXNoSGV4CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCQEFdmFsdWUBBQ50aGlzRXBvY2hNaW5lcgUDU0VQCQCkAwEFDHRoaXNFcG9jaFJlZgUDU0VQBQxibG9ja0hhc2hIZXgFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARJleHRlbmRNYWluQ2hhaW5fdjIEDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgFZXBvY2gaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgEC2NoZWNrQ2xUb0VsCQEecmVxdWlyZUNsVG9FbFRyYW5zZmVyc0Rpc2FibGVkAAMJAAACBQtjaGVja0NsVG9FbAULY2hlY2tDbFRvRWwEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IECmNoZWNrQ2hhaW4JAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQFBHVuaXQDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQOY2hlY2tSZWZlcmVuY2UJARJpc1JlZmVyZW5jZUNvcnJlY3QCBQxyZWZlcmVuY2VIZXgFEm1haW5DaGFpbkxhc3RCbG9jawMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDXRoaXNFcG9jaE1ldGEEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIEVW5pdAkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKwCAgkArAICCQClCAEIBQFpDG9yaWdpbkNhbGxlcgUDU0VQCQCkAwEFDm1haW5DaGFpbkVwb2NoBQNTRVAFDGJsb2NrSGFzaEhleAQFb3RoZXIFByRtYXRjaDAJAAIBAhVFcG9jaCBhbHJlYWR5IHN0YXJ0ZWQEFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQEdZ2V0VXBkYXRlRmluYWxpemVkQmxvY2tBY3Rpb24DCAUBaQxvcmlnaW5DYWxsZXIFDGJsb2NrSGFzaEhleAUObWFpbkNoYWluRXBvY2gEDm5ld0NoYWluSGVpZ2h0CQBkAgUPbWFpbkNoYWluSGVpZ2h0AAEJAM4IAgkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQcFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFEm1haW5DaGFpbkxhc3RCbG9jawgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgA////////////AQkAzAgCCQEQbWtDaGFpbk1ldGFFbnRyeQMFC21haW5DaGFpbklkBQ5uZXdDaGFpbkhlaWdodAUMYmxvY2tIYXNoSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPbWluZXJDaGFpbklkS2V5AQgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIFDXRoaXNFcG9jaE1ldGEFA25pbAUUdXBkYXRlRmluYWxpemVkQmxvY2sJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQESZXh0ZW5kTWFpbkNoYWluX3YzBQxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoGmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4F2xhc3RDbFRvRWxUcmFuc2ZlckluZGV4BAtjaGVja0VsVG9DbAkBHXJlcXVpcmVDbFRvRWxUcmFuc2ZlcnNFbmFibGVkAAMJAAACBQtjaGVja0VsVG9DbAULY2hlY2tFbFRvQ2wEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IECmNoZWNrQ2hhaW4JAR1lbnN1cmVFeHBlY3RlZE9ySW5hY3RpdmVDaGFpbgMIBQFpDG9yaWdpbkNhbGxlcgULbWFpbkNoYWluSWQFBHVuaXQDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQOY2hlY2tSZWZlcmVuY2UJARJpc1JlZmVyZW5jZUNvcnJlY3QCBQxyZWZlcmVuY2VIZXgFEm1haW5DaGFpbkxhc3RCbG9jawMJAAACBQ5jaGVja1JlZmVyZW5jZQUOY2hlY2tSZWZlcmVuY2UEDmNoZWNrVHJhbnNmZXJzCQEWZW5zdXJlQ29ycmVjdFRyYW5zZmVycwMICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al83BRdsYXN0Q2xUb0VsVHJhbnNmZXJJbmRleAYDCQAAAgUOY2hlY2tUcmFuc2ZlcnMFDmNoZWNrVHJhbnNmZXJzBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQ5tYWluQ2hhaW5FcG9jaAUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkAwkAAAIFDXRoaXNFcG9jaE1ldGEFDXRoaXNFcG9jaE1ldGEEFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQEdZ2V0VXBkYXRlRmluYWxpemVkQmxvY2tBY3Rpb24DCAUBaQxvcmlnaW5DYWxsZXIFDGJsb2NrSGFzaEhleAUObWFpbkNoYWluRXBvY2gEDm5ld0NoYWluSGVpZ2h0CQBkAgUPbWFpbkNoYWluSGVpZ2h0AAEJAM4IAgkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQcFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFEm1haW5DaGFpbkxhc3RCbG9jawgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgFF2xhc3RDbFRvRWxUcmFuc2ZlckluZGV4CQDMCAIJARBta0NoYWluTWV0YUVudHJ5AwULbWFpbkNoYWluSWQFDm5ld0NoYWluSGVpZ2h0BQxibG9ja0hhc2hIZXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgULbWFpbkNoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgUNdGhpc0Vwb2NoTWV0YQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBzdGFydEFsdENoYWluX3YyBAxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoGmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4BAtjaGVja0NsVG9FbAkBHnJlcXVpcmVDbFRvRWxUcmFuc2ZlcnNEaXNhYmxlZAADCQAAAgULY2hlY2tDbFRvRWwFC2NoZWNrQ2xUb0VsBA5jaGVja0Jsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4AwkAAAIFDmNoZWNrQmxvY2tIYXNoBQ5jaGVja0Jsb2NrSGFzaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFBWVwb2NoAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBA0kdDAyMTgwNTIxODgzCQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4BA5yZWZDaGFpbkhlaWdodAgFDSR0MDIxODA1MjE4ODMCXzEECHJlZkVwb2NoCAUNJHQwMjE4MDUyMTg4MwJfMgQGcmVmUmVmCAUNJHQwMjE4MDUyMTg4MwJfMwQMcmVmR2VuZXJhdG9yCAUNJHQwMjE4MDUyMTg4MwJfNAQOZmluYWxpemVkRXBvY2gICQEJYmxvY2tNZXRhAQkBEUBleHRyTmF0aXZlKDEwNTgpAQURZmluYWxpemVkQmxvY2tLZXkCXzIECGVwb2NoUmVmAwkAZwIFCHJlZkVwb2NoBQ5maW5hbGl6ZWRFcG9jaAUIcmVmRXBvY2gJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICI2NhbiBub3Qgc3RhcnQgYWx0IGNoYWluIGZyb20gZXBvY2ggCQCkAwEFCHJlZkVwb2NoAggsIGVwb2NoIAkApAMBBQ5maW5hbGl6ZWRFcG9jaAINIGlzIGZpbmFsaXplZAQKY2hlY2tDaGFpbgkBHWVuc3VyZUV4cGVjdGVkT3JJbmFjdGl2ZUNoYWluAwgFAWkMb3JpZ2luQ2FsbGVyBQttYWluQ2hhaW5JZAUMcmVmZXJlbmNlSGV4AwkAAAIFCmNoZWNrQ2hhaW4FCmNoZWNrQ2hhaW4ECm5ld0NoYWluSWQJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAAAQQObmV3Q2hhaW5IZWlnaHQJAGQCCAkBCWJsb2NrTWV0YQEFDHJlZmVyZW5jZUhleAJfMQABBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQhlcG9jaFJlZgUDU0VQBQxibG9ja0hhc2hIZXgEBW90aGVyBQckbWF0Y2gwCQACAQIVRXBvY2ggYWxyZWFkeSBzdGFydGVkCQDMCAIFDXRoaXNFcG9jaE1ldGEJAMwIAgkBEG1rQmxvY2tNZXRhRW50cnkHBQxibG9ja0hhc2hIZXgFDm5ld0NoYWluSGVpZ2h0BQxyZWZlcmVuY2VIZXgIBQFpDG9yaWdpbkNhbGxlcgUKbmV3Q2hhaW5JZAUaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgA////////////AQkAzAgCCQELU3RyaW5nRW50cnkCCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQpuZXdDaGFpbklkBQxibG9ja0hhc2hIZXgJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQpuZXdDaGFpbklkBQ5uZXdDaGFpbkhlaWdodAUMYmxvY2tIYXNoSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPbWluZXJDaGFpbklkS2V5AQgFAWkMb3JpZ2luQ2FsbGVyBQpuZXdDaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUKbmV3Q2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ1zdXBwb3J0ZXJzS2V5AQUKbmV3Q2hhaW5JZAkApQgBCAUBaQxvcmlnaW5DYWxsZXIJAMwIAgkBDEludGVnZXJFbnRyeQIFDmxhc3RDaGFpbklkS2V5BQpuZXdDaGFpbklkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEQc3RhcnRBbHRDaGFpbl92MwUMYmxvY2tIYXNoSGV4DHJlZmVyZW5jZUhleAVlcG9jaBplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleBdsYXN0Q2xUb0VsVHJhbnNmZXJJbmRleAQLY2hlY2tFbFRvQ2wJAR1yZXF1aXJlQ2xUb0VsVHJhbnNmZXJzRW5hYmxlZAADCQAAAgULY2hlY2tFbFRvQ2wFC2NoZWNrRWxUb0NsBA5jaGVja0Jsb2NrSGFzaAkBEXZhbGlkYXRlQmxvY2tIYXNoAQUMYmxvY2tIYXNoSGV4AwkAAAIFDmNoZWNrQmxvY2tIYXNoBQ5jaGVja0Jsb2NrSGFzaAQKY2hlY2tFcG9jaAkBEmVuc3VyZUNvcnJlY3RFcG9jaAEFBWVwb2NoAwkAAAIFCmNoZWNrRXBvY2gFCmNoZWNrRXBvY2gEDmNoZWNrR2VuZXJhdG9yCQERZW5zdXJlTWluaW5nRXBvY2gBCAUBaQxvcmlnaW5DYWxsZXIDCQAAAgUOY2hlY2tHZW5lcmF0b3IFDmNoZWNrR2VuZXJhdG9yBA0kdDAyMzY0MTIzNzYzCQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4BA5yZWZDaGFpbkhlaWdodAgFDSR0MDIzNjQxMjM3NjMCXzEECHJlZkVwb2NoCAUNJHQwMjM2NDEyMzc2MwJfMgQGcmVmUmVmCAUNJHQwMjM2NDEyMzc2MwJfMwQMcmVmR2VuZXJhdG9yCAUNJHQwMjM2NDEyMzc2MwJfNAQLcmVmSWdub3JlZDUIBQ0kdDAyMzY0MTIzNzYzAl81BAtyZWZJZ25vcmVkNggFDSR0MDIzNjQxMjM3NjMCXzYEEHJlZlRyYW5zZmVySW5kZXgIBQ0kdDAyMzY0MTIzNzYzAl83BA5maW5hbGl6ZWRFcG9jaAgJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRFmaW5hbGl6ZWRCbG9ja0tleQJfMgQIZXBvY2hSZWYDCQBnAgUIcmVmRXBvY2gFDmZpbmFsaXplZEVwb2NoBQhyZWZFcG9jaAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgIjQ2FuIG5vdCBzdGFydCBhbHQgY2hhaW4gZnJvbSBlcG9jaCAJAKQDAQUIcmVmRXBvY2gCCCwgZXBvY2ggCQCkAwEFDmZpbmFsaXplZEVwb2NoAg0gaXMgZmluYWxpemVkBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFC21haW5DaGFpbklkBQxyZWZlcmVuY2VIZXgDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQOY2hlY2tUcmFuc2ZlcnMJARZlbnN1cmVDb3JyZWN0VHJhbnNmZXJzAwUQcmVmVHJhbnNmZXJJbmRleAUXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgGAwkAAAIFDmNoZWNrVHJhbnNmZXJzBQ5jaGVja1RyYW5zZmVycwQKbmV3Q2hhaW5JZAkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUObGFzdENoYWluSWRLZXkAAAABBA5uZXdDaGFpbkhlaWdodAkAZAIFDnJlZkNoYWluSGVpZ2h0AAEEDXRoaXNFcG9jaE1ldGEEByRtYXRjaDAJAQllcG9jaE1ldGEBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIEVW5pdAkBC1N0cmluZ0VudHJ5AgkBDGVwb2NoTWV0YUtleQEFBmhlaWdodAkArAICCQCsAgIJAKwCAgkArAICCQClCAEIBQFpDG9yaWdpbkNhbGxlcgUDU0VQCQCkAwEFCGVwb2NoUmVmBQNTRVAFDGJsb2NrSGFzaEhleAQFb3RoZXIFByRtYXRjaDAJAAIBAhVFcG9jaCBhbHJlYWR5IHN0YXJ0ZWQJAMwIAgUNdGhpc0Vwb2NoTWV0YQkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQcFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFDHJlZmVyZW5jZUhleAgFAWkMb3JpZ2luQ2FsbGVyBQpuZXdDaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAUXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGNoYWluRmlyc3RCbG9ja0lkS2V5AQUKbmV3Q2hhaW5JZAUMYmxvY2tIYXNoSGV4CQDMCAIJARBta0NoYWluTWV0YUVudHJ5AwUKbmV3Q2hhaW5JZAUObmV3Q2hhaW5IZWlnaHQFDGJsb2NrSGFzaEhleAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD21pbmVyQ2hhaW5JZEtleQEIBQFpDG9yaWdpbkNhbGxlcgUKbmV3Q2hhaW5JZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFCm5ld0NoYWluSWQIBQFpDG9yaWdpbkNhbGxlcgUObmV3Q2hhaW5IZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQttYWluQ2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCCQENc3VwcG9ydGVyc0tleQEFCm5ld0NoYWluSWQJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5sYXN0Q2hhaW5JZEtleQUKbmV3Q2hhaW5JZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEWV4dGVuZEFsdENoYWluX3YyBQdjaGFpbklkDGJsb2NrSGFzaEhleAxyZWZlcmVuY2VIZXgFZXBvY2gaZWxUb0NsVHJhbnNmZXJzUm9vdEhhc2hIZXgEC2NoZWNrQ2xUb0VsCQEecmVxdWlyZUNsVG9FbFRyYW5zZmVyc0Rpc2FibGVkAAMJAAACBQtjaGVja0NsVG9FbAULY2hlY2tDbFRvRWwEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEE2NoYWluRmlyc3RCbG9ja01ldGEJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQdjaGFpbklkBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJANwEAQgFE2NoYWluRmlyc3RCbG9ja01ldGECXzMDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQNJHQwMjYxMzcyNjE5MQkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMjYxMzcyNjE5MQJfMQQOY2hhaW5MYXN0QmxvY2sIBQ0kdDAyNjEzNzI2MTkxAl8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAUOY2hhaW5MYXN0QmxvY2sDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5uZXdDaGFpbkhlaWdodAkAZAIFC2NoYWluSGVpZ2h0AAEECXByZXZFcG9jaAgJAQlibG9ja01ldGEBBQxyZWZlcmVuY2VIZXgCXzIEE3VwZGF0ZU1haW5DaGFpbkRhdGEDCQBmAgkBEXN1cHBvcnRpbmdCYWxhbmNlAQUHY2hhaW5JZAkAaQIFFGNvbXB1dGVkVG90YWxCYWxhbmNlAAIEC2xhc3RDaGFpbklkCQELdmFsdWVPckVsc2UCCQCfCAEFDmxhc3RDaGFpbklkS2V5AAAEFHVwZGF0ZUZpbmFsaXplZEJsb2NrCQEdZ2V0VXBkYXRlRmluYWxpemVkQmxvY2tBY3Rpb24DCAUBaQxvcmlnaW5DYWxsZXIFDGJsb2NrSGFzaEhleAUJcHJldkVwb2NoCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARRjaGFpbkZvcmtlZEhlaWdodEtleQEFC21haW5DaGFpbklkCAUTY2hhaW5GaXJzdEJsb2NrTWV0YQJfMQkAzAgCCQEMSW50ZWdlckVudHJ5AgUObWFpbkNoYWluSWRLZXkFB2NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIFF2ZpcnN0VmFsaWRBbHRDaGFpbklkS2V5CQBkAgULbGFzdENoYWluSWQAAQUDbmlsBRR1cGRhdGVGaW5hbGl6ZWRCbG9jawUDbmlsBA10aGlzRXBvY2hNZXRhBAckbWF0Y2gwCQEJZXBvY2hNZXRhAQUGaGVpZ2h0AwkAAQIFByRtYXRjaDACBFVuaXQJAQtTdHJpbmdFbnRyeQIJAQxlcG9jaE1ldGFLZXkBBQZoZWlnaHQJAKwCAgkArAICCQCsAgIJAKwCAgkApQgBCAUBaQxvcmlnaW5DYWxsZXIFA1NFUAkApAMBBQlwcmV2RXBvY2gFA1NFUAUMYmxvY2tIYXNoSGV4BAVvdGhlcgUHJG1hdGNoMAkAAgECFUVwb2NoIGFscmVhZHkgc3RhcnRlZAQddXBkYXRlTWFpbkNoYWluTGFzdE1pbmVkQmxvY2sDAwkAAAIFE3VwZGF0ZU1haW5DaGFpbkRhdGEFA25pbAkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkBDG1pbmVyQ2hhaW5JZAEIBQFpDG9yaWdpbkNhbGxlcgAABQdjaGFpbklkBwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIIBRNjaGFpbkZpcnN0QmxvY2tNZXRhAl8xBQNuaWwFA25pbAkAzggCCQDOCAIJAM4IAgkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQcFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFDHJlZmVyZW5jZUhleAgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAD///////////8BCQDMCAIJARBta0NoYWluTWV0YUVudHJ5AwUHY2hhaW5JZAUObmV3Q2hhaW5IZWlnaHQFDGJsb2NrSGFzaEhleAkAzAgCBQ10aGlzRXBvY2hNZXRhCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPbWluZXJDaGFpbklkS2V5AQgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESY2hhaW5MYXN0SGVpZ2h0S2V5AgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBQ5uZXdDaGFpbkhlaWdodAUDbmlsBRN1cGRhdGVNYWluQ2hhaW5EYXRhCQEMYWRkU3VwcG9ydGVyAgUHY2hhaW5JZAgFAWkMb3JpZ2luQ2FsbGVyBR11cGRhdGVNYWluQ2hhaW5MYXN0TWluZWRCbG9jawkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARFleHRlbmRBbHRDaGFpbl92MwYHY2hhaW5JZAxibG9ja0hhc2hIZXgMcmVmZXJlbmNlSGV4BWVwb2NoGmVsVG9DbFRyYW5zZmVyc1Jvb3RIYXNoSGV4F2xhc3RDbFRvRWxUcmFuc2ZlckluZGV4BAtjaGVja0VsVG9DbAkBHXJlcXVpcmVDbFRvRWxUcmFuc2ZlcnNFbmFibGVkAAMJAAACBQtjaGVja0VsVG9DbAULY2hlY2tFbFRvQ2wEDmNoZWNrQmxvY2tIYXNoCQERdmFsaWRhdGVCbG9ja0hhc2gBBQxibG9ja0hhc2hIZXgDCQAAAgUOY2hlY2tCbG9ja0hhc2gFDmNoZWNrQmxvY2tIYXNoBApjaGVja0Vwb2NoCQESZW5zdXJlQ29ycmVjdEVwb2NoAQUFZXBvY2gDCQAAAgUKY2hlY2tFcG9jaAUKY2hlY2tFcG9jaAQOY2hlY2tHZW5lcmF0b3IJARFlbnN1cmVNaW5pbmdFcG9jaAEIBQFpDG9yaWdpbkNhbGxlcgMJAAACBQ5jaGVja0dlbmVyYXRvcgUOY2hlY2tHZW5lcmF0b3IEE2NoYWluRmlyc3RCbG9ja01ldGEJAQlibG9ja01ldGEBCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEUY2hhaW5GaXJzdEJsb2NrSWRLZXkBBQdjaGFpbklkBApjaGVja0NoYWluCQEdZW5zdXJlRXhwZWN0ZWRPckluYWN0aXZlQ2hhaW4DCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJANwEAQgFE2NoYWluRmlyc3RCbG9ja01ldGECXzMDCQAAAgUKY2hlY2tDaGFpbgUKY2hlY2tDaGFpbgQNJHQwMjg3MzUyODc4OQkBCWNoYWluTWV0YQEFB2NoYWluSWQEC2NoYWluSGVpZ2h0CAUNJHQwMjg3MzUyODc4OQJfMQQOY2hhaW5MYXN0QmxvY2sIBQ0kdDAyODczNTI4Nzg5Al8yBA5jaGVja1JlZmVyZW5jZQkBEmlzUmVmZXJlbmNlQ29ycmVjdAIFDHJlZmVyZW5jZUhleAUOY2hhaW5MYXN0QmxvY2sDCQAAAgUOY2hlY2tSZWZlcmVuY2UFDmNoZWNrUmVmZXJlbmNlBA5jaGVja1RyYW5zZmVycwkBFmVuc3VyZUNvcnJlY3RUcmFuc2ZlcnMDCAkBCWJsb2NrTWV0YQEFDHJlZmVyZW5jZUhleAJfNwUXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgGAwkAAAIFDmNoZWNrVHJhbnNmZXJzBQ5jaGVja1RyYW5zZmVycwQObmV3Q2hhaW5IZWlnaHQJAGQCBQtjaGFpbkhlaWdodAABBAlwcmV2RXBvY2gICQEJYmxvY2tNZXRhAQUMcmVmZXJlbmNlSGV4Al8yBBN1cGRhdGVNYWluQ2hhaW5EYXRhAwkAZgIJARFzdXBwb3J0aW5nQmFsYW5jZQEFB2NoYWluSWQJAGkCBRRjb21wdXRlZFRvdGFsQmFsYW5jZQACBAtsYXN0Q2hhaW5JZAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQ5sYXN0Q2hhaW5JZEtleQAABBR1cGRhdGVGaW5hbGl6ZWRCbG9jawkBHWdldFVwZGF0ZUZpbmFsaXplZEJsb2NrQWN0aW9uAwgFAWkMb3JpZ2luQ2FsbGVyBQxibG9ja0hhc2hIZXgFCXByZXZFcG9jaAkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEUY2hhaW5Gb3JrZWRIZWlnaHRLZXkBBQttYWluQ2hhaW5JZAgFE2NoYWluRmlyc3RCbG9ja01ldGECXzEJAMwIAgkBDEludGVnZXJFbnRyeQIFDm1haW5DaGFpbklkS2V5BQdjaGFpbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdmaXJzdFZhbGlkQWx0Q2hhaW5JZEtleQkAZAIFC2xhc3RDaGFpbklkAAEFA25pbAUUdXBkYXRlRmluYWxpemVkQmxvY2sFA25pbAQNdGhpc0Vwb2NoTWV0YQQHJG1hdGNoMAkBCWVwb2NoTWV0YQEFBmhlaWdodAMJAAECBQckbWF0Y2gwAgRVbml0CQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkArAICCQCsAgIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBQNTRVAJAKQDAQUJcHJldkVwb2NoBQNTRVAFDGJsb2NrSGFzaEhleAQFb3RoZXIFByRtYXRjaDAJAAIBAhVFcG9jaCBhbHJlYWR5IHN0YXJ0ZWQDCQAAAgUNdGhpc0Vwb2NoTWV0YQUNdGhpc0Vwb2NoTWV0YQQddXBkYXRlTWFpbkNoYWluTGFzdE1pbmVkQmxvY2sDAwkAAAIFE3VwZGF0ZU1haW5DaGFpbkRhdGEFA25pbAkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkBDG1pbmVyQ2hhaW5JZAEIBQFpDG9yaWdpbkNhbGxlcgAABQdjaGFpbklkBwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmNoYWluTGFzdEhlaWdodEtleQIFC21haW5DaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIIBRNjaGFpbkZpcnN0QmxvY2tNZXRhAl8xBQNuaWwFA25pbAkAzggCCQDOCAIJAM4IAgkAzAgCCQEQbWtCbG9ja01ldGFFbnRyeQcFDGJsb2NrSGFzaEhleAUObmV3Q2hhaW5IZWlnaHQFDHJlZmVyZW5jZUhleAgFAWkMb3JpZ2luQ2FsbGVyBQdjaGFpbklkBRplbFRvQ2xUcmFuc2ZlcnNSb290SGFzaEhleAUXbGFzdENsVG9FbFRyYW5zZmVySW5kZXgJAMwIAgkBEG1rQ2hhaW5NZXRhRW50cnkDBQdjaGFpbklkBQ5uZXdDaGFpbkhlaWdodAUMYmxvY2tIYXNoSGV4CQDMCAIFDXRoaXNFcG9jaE1ldGEJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9taW5lckNoYWluSWRLZXkBCAUBaQxvcmlnaW5DYWxsZXIFB2NoYWluSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJARJjaGFpbkxhc3RIZWlnaHRLZXkCBQdjaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFDm5ld0NoYWluSGVpZ2h0BQNuaWwFE3VwZGF0ZU1haW5DaGFpbkRhdGEJAQxhZGRTdXBwb3J0ZXICBQdjaGFpbklkCAUBaQxvcmlnaW5DYWxsZXIFHXVwZGF0ZU1haW5DaGFpbkxhc3RNaW5lZEJsb2NrCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBGpvaW4BDXJld2FyZEFkZHJlc3MKAR1lbnN1cmVOb3RPdmVycmlkZU90aGVyTWluZXJQawEMZWxBZGRyZXNzSGV4BAckbWF0Y2gwCQChCAEJAQptaW5lclBrS2V5AQUMZWxBZGRyZXNzSGV4AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwAwkAAAIFAnBrCAUBaRVvcmlnaW5DYWxsZXJQdWJsaWNLZXkFBHVuaXQJAAIBCQCsAgIJAKwCAgkArAICAhFFTCBtaW5lciBhZGRyZXNzIAUMZWxBZGRyZXNzSGV4AhggaXMgYWxyZWFkeSBsaW5rZWQgd2l0aCAJANgEAQUCcGsFBHVuaXQDCQEBIQEJAQ9pc0NvbnRyYWN0U2V0dXAACQACAQIfVGhlIGNvbnRyYWN0IGhhcyBub3QgeWV0IHNldCB1cAMJAGYCBQtNSU5fQkFMQU5DRQgJAO8HAQgFAWkMb3JpZ2luQ2FsbGVyCmdlbmVyYXRpbmcJAAIBCQCsAgIJAKwCAgkArAICAiFJbnN1ZmZpY2llbnQgZ2VuZXJhdGluZyBiYWxhbmNlOiAJAKQDAQgJAO8HAQgFAWkMb3JpZ2luQ2FsbGVyCmdlbmVyYXRpbmcCDC4gUmVxdWlyZWQ6IAkApAMBBQtNSU5fQkFMQU5DRQMJAQIhPQIJAMgBAQUNcmV3YXJkQWRkcmVzcwAUCQACAQIlcmV3YXJkQWRkcmVzcyBzaG91bGQgYmUgYW4gTDIgYWRkcmVzcwMJAGcCCQCQAwEFCWFsbE1pbmVycwAyCQACAQIPdG9vIG1hbnkgbWluZXJzCgEOY2hlY2tFeGlzdGVuY2UCBmV4aXN0cwVtaW5lcgMFBmV4aXN0cwYJAAACBQVtaW5lcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEDWFscmVhZHlFeGlzdHMKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAcKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDmNoZWNrRXhpc3RlbmNlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIDBQ1hbHJlYWR5RXhpc3RzBQNuaWwECG5ld01pbmVyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQQcmV3YXJkQWRkcmVzc0hleAkA3AQBBQ1yZXdhcmRBZGRyZXNzBAVjaGVjawkBHWVuc3VyZU5vdE92ZXJyaWRlT3RoZXJNaW5lclBrAQUQcmV3YXJkQWRkcmVzc0hleAMJAAACBQVjaGVjawUFY2hlY2sECW5ld01pbmVycwMJAAACCQCQAwEFCWFsbE1pbmVycwAABQhuZXdNaW5lcgkArAICCQCsAgIFDGFsbE1pbmVyc1N0cgUDU0VQBQhuZXdNaW5lcgQYZGVsZXRlT2xkUmV3YXJkQWRkcmVzc1BrBAckbWF0Y2gwCQCiCAEJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQhuZXdNaW5lcgMJAAECBQckbWF0Y2gwAgZTdHJpbmcECm9sZEFkZHJlc3MFByRtYXRjaDADCQAAAgUKb2xkQWRkcmVzcwkA3AQBBQ1yZXdhcmRBZGRyZXNzBQNuaWwJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBCm1pbmVyUGtLZXkBBQpvbGRBZGRyZXNzBQNuaWwFA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFDGFsbE1pbmVyc0tleQUJbmV3TWluZXJzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQhuZXdNaW5lcgkArAICAgIweAUQcmV3YXJkQWRkcmVzc0hleAkAzAgCCQELQmluYXJ5RW50cnkCCQEKbWluZXJQa0tleQEFEHJld2FyZEFkZHJlc3NIZXgIBQFpFW9yaWdpbkNhbGxlclB1YmxpY0tleQUDbmlsBRhkZWxldGVPbGRSZXdhcmRBZGRyZXNzUGsJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEFbGVhdmUABAxsZWF2aW5nTWluZXIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCgEQc2tpcExlYXZpbmdNaW5lcgIDYWNjBW1pbmVyAwkAAAIFBW1pbmVyBQxsZWF2aW5nTWluZXIFA2FjYwkAzQgCBQNhY2MFBW1pbmVyBA9yZW1haW5pbmdNaW5lcnMKAAIkbAUJYWxsTWluZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARBza2lwTGVhdmluZ01pbmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIEDXJld2FyZEFkZHJLZXkJARVtaW5lclJld2FyZEFkZHJlc3NLZXkBBQxsZWF2aW5nTWluZXIEEXByZXZSZXdhcmRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhpcwUNcmV3YXJkQWRkcktleQIWbWluZXIgaGFzIG5ldmVyIGpvaW5lZAMJAAACBQ50aGlzRXBvY2hNaW5lcggFAWkMb3JpZ2luQ2FsbGVyCQACAQIcZGVzaWduYXRlZCBtaW5lciBjYW4ndCBsZWF2ZQkAzAgCCQELU3RyaW5nRW50cnkCBQxhbGxNaW5lcnNLZXkJALoJAgUPcmVtYWluaW5nTWluZXJzBQNTRVAFA25pbAFpAQh0cmFuc2ZlcgEQZGVzdEVsQWRkcmVzc0hleAQLY2hlY2tDbFRvRWwJAR1yZXF1aXJlQ2xUb0VsVHJhbnNmZXJzRW5hYmxlZAADCQAAAgULY2hlY2tDbFRvRWwFC2NoZWNrQ2xUb0VsBAxjaGVja1BheW1lbnQDCQAAAgkAkAMBCAUBaQhwYXltZW50cwABBgkAAgEJAKwCAgIvRXhwZWN0ZWQgb25lIHBheW1lbnQgYXMgYSB0cmFuc2ZlciBhbW91bnQsIGdvdCAJAKQDAQkAkAMBCAUBaQhwYXltZW50cwMJAAACBQxjaGVja1BheW1lbnQFDGNoZWNrUGF5bWVudAQKdG9rZW5JZFN0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQUKdG9rZW5JZEtleQQHdG9rZW5JZAkA2QQBBQp0b2tlbklkU3RyBAF0CQCRAwIIBQFpCHBheW1lbnRzAAAEDGNoZWNrQXNzZXRJZAQHJG1hdGNoMAgFAXQHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAdhc3NldElkBQckbWF0Y2gwAwkAAAIFB2Fzc2V0SWQFB3Rva2VuSWQGCQACAQkArAICCQCsAgIJAKwCAgIJRXhwZWN0ZWQgBQp0b2tlbklkU3RyAhUgaW4gdGhlIHBheW1lbnQsIGdvdCAJANgEAQUHYXNzZXRJZAkAAgEJAKwCAgkArAICAglFeHBlY3RlZCAFCnRva2VuSWRTdHICGiBpbiB0aGUgcGF5bWVudCwgZ290IFdhdmVzAwkAAAIFDGNoZWNrQXNzZXRJZAUMY2hlY2tBc3NldElkBAlsYXN0SW5kZXgICQEJYmxvY2tNZXRhAQUSbWFpbkNoYWluTGFzdEJsb2NrAl83BAlxdWV1ZVNpemUJAGQCCQBlAgUUbmF0aXZlVHJhbnNmZXJzQ291bnQFCWxhc3RJbmRleAABBA9jaGVja1F1ZXVlTGltaXQDCQBmAgCgAQUJcXVldWVTaXplCQEKYW1vdW50R3RFcQMFAXQAwIQ9BQlxdWV1ZVNpemUDCQBmAgDADAUJcXVldWVTaXplCQEKYW1vdW50R3RFcQMFAXQAgK3iBAUJcXVldWVTaXplAwkAZgIAgBkFCXF1ZXVlU2l6ZQkBCmFtb3VudEd0RXEDBQF0AIDC1y8FCXF1ZXVlU2l6ZQMJAGYCAIAyBQlxdWV1ZVNpemUJAQphbW91bnRHdEVxAwUBdACAlOvcAwUJcXVldWVTaXplCQACAQkArAICCQCsAgICI1RyYW5zZmVycyBkZW5pZWQgZm9yIHF1ZXVlIHNpemUgb2YgCQCkAwEFCXF1ZXVlU2l6ZQIoLiBXYWl0IHVudGlsIGN1cnJlbnQgdHJhbnNmZXJzIHByb2Nlc3NlZAMJAAACBQ9jaGVja1F1ZXVlTGltaXQFD2NoZWNrUXVldWVMaW1pdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXbmF0aXZlVHJhbnNmZXJzQ291bnRLZXkJAGQCBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAABCQDMCAIJARVta05hdGl2ZVRyYW5zZmVyRW50cnkDBRRuYXRpdmVUcmFuc2ZlcnNDb3VudAUQZGVzdEVsQWRkcmVzc0hleAgFAXQGYW1vdW50CQDMCAIJAQRCdXJuAgUHdG9rZW5JZAgFAXQGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEId2l0aGRyYXcEDGJsb2NrSGFzaEhleAttZXJrbGVQcm9vZhR0cmFuc2ZlckluZGV4SW5CbG9jawZhbW91bnQEEXdpdGhkcmF3QmxvY2tNZXRhCQEJYmxvY2tNZXRhAQUMYmxvY2tIYXNoSGV4BBN3aXRoZHJhd0Jsb2NrSGVpZ2h0CAURd2l0aGRyYXdCbG9ja01ldGECXzEEFGZpbmFsaXplZEJsb2NrSGVpZ2h0CAkBCWJsb2NrTWV0YQEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFEWZpbmFsaXplZEJsb2NrS2V5Al8xBBhtYWluQ2hhaW5MYXN0QmxvY2tIZWlnaHQICQEJYmxvY2tNZXRhAQUSbWFpbkNoYWluTGFzdEJsb2NrAl8xAwkAZgIFE3dpdGhkcmF3QmxvY2tIZWlnaHQFFGZpbmFsaXplZEJsb2NrSGVpZ2h0CQACAQkArAICCQCsAgIJAKwCAgIKRUwgYmxvY2sgIwkApAMBBRN3aXRoZHJhd0Jsb2NrSGVpZ2h0Ai0gaXMgbm90IGZpbmFsaXplZC4gVGhlIGN1cnJlbnQgZmluYWxpemVkIGlzICMJAKQDAQUUZmluYWxpemVkQmxvY2tIZWlnaHQEFHdpdGhkcmF3QmxvY2tDaGFpbklkCAURd2l0aGRyYXdCbG9ja01ldGECXzUEC2lzTWFpbkNoYWluCQAAAgUUd2l0aGRyYXdCbG9ja0NoYWluSWQFC21haW5DaGFpbklkBBJyZWxhdGVzVG9NYWluQ2hhaW4EByRtYXRjaDAJAJ8IAQkBFGNoYWluRm9ya2VkSGVpZ2h0S2V5AQUUd2l0aGRyYXdCbG9ja0NoYWluSWQDCQABAgUHJG1hdGNoMAIDSW50BAxmb3JrZWRIZWlnaHQFByRtYXRjaDAJAGYCBQxmb3JrZWRIZWlnaHQFE3dpdGhkcmF3QmxvY2tIZWlnaHQJAAIBCQCsAgIJAKwCAgkArAICBQxibG9ja0hhc2hIZXgCHSBpcyBvbiBhbiBhbHRlcm5hdGl2ZSBjaGFpbiAjCQCkAwEFFHdpdGhkcmF3QmxvY2tDaGFpbklkAjggdGhhdCB3YXMgbm90IGFwcHJvdmVkIGJ5IG1ham9yaXR5LiBXYWl0IGZvciBzb21lIGJsb2NrcwMDBQtpc01haW5DaGFpbgYFEnJlbGF0ZXNUb01haW5DaGFpbgQJcmVjaXBpZW50CAUBaQxvcmlnaW5DYWxsZXIED3JlY2lwaWVudFBrSGFzaAkAyQECCQDKAQIIBQlyZWNpcGllbnQFYnl0ZXMAAgUUUFVCTElDX0tFWV9IQVNIX1NJWkUED3plcm9BbW91bnRCeXRlcwEsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEC2Ftb3VudEJ5dGVzCQCaAwEFBmFtb3VudAQLZWxFdmVudERhdGEJAMsBAgkAywECBQ9yZWNpcGllbnRQa0hhc2gJAMkBAgUPemVyb0Ftb3VudEJ5dGVzCQBlAgkAyAEBBQ96ZXJvQW1vdW50Qnl0ZXMJAMgBAQULYW1vdW50Qnl0ZXMFC2Ftb3VudEJ5dGVzBBFlbEV2ZW50RGF0YURpZ2VzdAkA8BUBBQtlbEV2ZW50RGF0YQQSY2FsY3VsYXRlZFJvb3RIYXNoCQC9BQMFC21lcmtsZVByb29mBRFlbEV2ZW50RGF0YURpZ2VzdAUUdHJhbnNmZXJJbmRleEluQmxvY2sEEGV4cGVjdGVkUm9vdEhhc2gIBRF3aXRoZHJhd0Jsb2NrTWV0YQJfNgMJAAACBRJjYWxjdWxhdGVkUm9vdEhhc2gFEGV4cGVjdGVkUm9vdEhhc2gEB3Rva2VuSWQJANkEAQkBEUBleHRyTmF0aXZlKDEwNTgpAQUKdG9rZW5JZEtleQQMdHJhbnNmZXJzS2V5CQEXYmxvY2tFbFRvQ2xUcmFuc2ZlcnNLZXkBBQxibG9ja0hhc2hIZXgJAMwIAgkBB1JlaXNzdWUDBQd0b2tlbklkBQZhbW91bnQGCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFCXJlY2lwaWVudAUGYW1vdW50BQd0b2tlbklkCQDMCAIJAQtTdHJpbmdFbnRyeQIFDHRyYW5zZmVyc0tleQkBCXNldE9yRmFpbAIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUMdHJhbnNmZXJzS2V5AgAFFHRyYW5zZmVySW5kZXhJbkJsb2NrBQNuaWwJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhRFeHBlY3RlZCByb290IGhhc2g6IAkA3AQBBRBleHBlY3RlZFJvb3RIYXNoAgcsIGdvdDogCQDcBAEFEmNhbGN1bGF0ZWRSb290SGFzaAIVLiBFdmVudCBkYXRhIGRpZ2VzdDogCQDaBAEFEWVsRXZlbnREYXRhRGlnZXN0Ah8uIENoZWNrIHlvdXIgd2l0aGRyYXcgYXJndW1lbnRzCQACAQkArAICCQCsAgICCUV4cGVjdGVkIAUMYmxvY2tIYXNoSGV4Ai8gdG8gYmUgZWl0aGVyIG9uIHRoZSBtYWluIGNoYWluIG9yIHJlbGF0ZSB0byBpdAFpAQVzZXR1cAQTZ2VuZXNpc0Jsb2NrSGFzaEhleBFtaW5lclJld2FyZEluR3dlaRlzdGFraW5nQ29udHJhY3RBZGRyZXNzQjU4EmVsQnJpZGdlQWRkcmVzc0hleAMJAQ9pc0NvbnRyYWN0U2V0dXAACQACAQIkVGhlIGNvbnRyYWN0IGhhcyBiZWVuIGFscmVhZHkgc2V0IHVwAwkAZgIAAAURbWluZXJSZXdhcmRJbkd3ZWkJAAIBAiRUaGUgbWluZXIgcmV3YXJkIG11c3QgYmUgbm9ubmVnYXRpdmUEEGdlbmVzaXNCbG9ja0hhc2gJAN0EAQUTZ2VuZXNpc0Jsb2NrSGFzaEhleAQHZW1wdHlQawEgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEE2dlbmVzaXNNaW5lckFkZHJlc3MJAKcIAQUHZW1wdHlQawQXZ2VuZXNpc0V0aFJld2FyZEFkZHJlc3MBFAAAAAAAAAAAAAAAAAAAAAAAAAAABBlnZW5lc2lzQmxvY2tSZWZlcmVuY2VIYXNoAkAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBAVpc3N1ZQkAwggFAgVVTklUMAIMTmF0aXZlIHRva2VuAAAACAYEB3Rva2VuSWQJALgIAQUFaXNzdWUEEGdlbmVzaXNCbG9ja01ldGEJAMsBAgkAywECCQDLAQIJAMsBAgkAywECCQDLAQIJAJoDAQAACQCaAwEFBmhlaWdodAkA3QQBBRlnZW5lc2lzQmxvY2tSZWZlcmVuY2VIYXNoCAUTZ2VuZXNpc01pbmVyQWRkcmVzcwVieXRlcwkAmgMBAAABAAkAmgMBAP///////////wEJAMwIAgkBC0JpbmFyeUVudHJ5AgkArAICBQpibG9ja01ldGFLBRNnZW5lc2lzQmxvY2tIYXNoSGV4BRBnZW5lc2lzQmxvY2tNZXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIJARRjaGFpbkZpcnN0QmxvY2tJZEtleQEAAAUTZ2VuZXNpc0Jsb2NrSGFzaEhleAkAzAgCCQEQbWtDaGFpbk1ldGFFbnRyeQMAAAAABRNnZW5lc2lzQmxvY2tIYXNoSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5taW5lclJld2FyZEtleQURbWluZXJSZXdhcmRJbkd3ZWkJAMwIAgkBC1N0cmluZ0VudHJ5AgUZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0tleQUZc3Rha2luZ0NvbnRyYWN0QWRkcmVzc0I1OAkAzAgCCQELU3RyaW5nRW50cnkCCQEMZXBvY2hNZXRhS2V5AQUGaGVpZ2h0CQCsAgIJAKwCAgkApQgBBRNnZW5lc2lzTWluZXJBZGRyZXNzAgMsMCwFE2dlbmVzaXNCbG9ja0hhc2hIZXgJAMwIAgkBC1N0cmluZ0VudHJ5AgURZmluYWxpemVkQmxvY2tLZXkFE2dlbmVzaXNCbG9ja0hhc2hIZXgJAMwIAgUFaXNzdWUJAMwIAgkBC1N0cmluZ0VudHJ5AgUKdG9rZW5JZEtleQkA2AQBBQd0b2tlbklkCQDMCAIJAQtTdHJpbmdFbnRyeQIFEmVsQnJpZGdlQWRkcmVzc0tleQkArAICAgIweAUSZWxCcmlkZ2VBZGRyZXNzSGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRdjbFRvRWxUcmFuc2ZlcnNFcG9jaEtleQAABQNuaWwAxmm0zw==", "height": 3246951, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: GPDrfDQ2Jpsvk5nSwYoCMcd5MEHcZSCcD2kGPSNpoy1M Next: 3dyZaun8aXdrUhLxUK6wZAxc6oi3XiTfHxWPo2ysQohP Diff:
OldNewDifferences
1414 let ADDRESS_SIZE = 26
1515
1616 let PUBLIC_KEY_HASH_SIZE = 20
17+
18+let ROOT_HASH_SIZE = 32
19+
20+let MAX_CL_TO_EL_TRANSFERS = 16
1721
1822 let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
1923
3943
4044 let elBridgeAddressKey = "elBridgeAddress"
4145
42-let prevRandaoHeightKey = "prevRandaoHeight"
46+let nativeTransfersCountKey = "nativeTransfersCount"
4347
44-let elToClTransfersEpochKey = "elToClTransfersEpoch"
48+let clToElTransfersEpochKey = "clToElTransfersEpoch"
4549
4650 func pad (i) = {
4751 let s = toString(i)
96100 func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId")
97101
98102
99-let elToClTransfersEpoch = valueOrElse(getInteger(this, elToClTransfersEpochKey), INT_MAX)
103+let nativeTransfersCount = valueOrElse(getInteger(this, nativeTransfersCountKey), 0)
100104
101-func requireElToClTransfersDisabled () = if ((elToClTransfersEpoch > height))
102- then unit
103- else throw((("EL to CL transfers activated on epoch #" + toString(height)) + ". Upgrade your client"))
105+func nativeTransferKey (index) = ("nativeTransfer_" + toString(index))
104106
105107
106-func requireElToClTransfersEnabled () = if ((height >= elToClTransfersEpoch))
108+func mkNativeTransferEntry (index,destElAddressHex,amount) = StringEntry(nativeTransferKey(index), ((("0x" + destElAddressHex) + SEP) + toString(amount)))
109+
110+
111+let clToElTransfersEpoch = valueOrElse(getInteger(this, clToElTransfersEpochKey), INT_MAX)
112+
113+func requireClToElTransfersDisabled () = if ((clToElTransfersEpoch > height))
107114 then unit
108- else throw(((("EL to CL transfers haven't activated on epoch #" + toString(height)) + ". Wait for activation on #") + toString(elToClTransfersEpoch)))
115+ else throw((("CL to EL transfers activated on epoch #" + toString(height)) + ". Upgrade your client"))
116+
117+
118+func requireClToElTransfersEnabled () = if ((height >= clToElTransfersEpoch))
119+ then unit
120+ else throw(((("CL to EL transfers haven't activated on epoch #" + toString(height)) + ". Wait for activation on #") + toString(clToElTransfersEpoch)))
121+
122+
123+func ensureCorrectTransfers (refTransferIndex,transferIndex,expectReward) = {
124+ let maxTransfers = if (expectReward)
125+ then (MAX_CL_TO_EL_TRANSFERS - 1)
126+ else MAX_CL_TO_EL_TRANSFERS
127+ let actualTransfers = (transferIndex - refTransferIndex)
128+ let checkNumber = if ((actualTransfers > maxTransfers))
129+ then throw(((("Allowed only " + toString(maxTransfers)) + " transfers, got ") + toString(actualTransfers)))
130+ else true
131+ if ((checkNumber == checkNumber))
132+ then if ((transferIndex >= nativeTransfersCount))
133+ then throw(((("Attempt to transfer #" + toString(transferIndex)) + ". Available transfers: ") + toString(nativeTransfersCount)))
134+ else true
135+ else throw("Strict value is not equal to itself.")
136+ }
137+
138+
139+func amountGtEq (t,gtEq,queueSize) = if ((t.amount >= gtEq))
140+ then true
141+ else throw((((((("Transferring amount " + toString(t.amount)) + " should be >= ") + toString(gtEq)) + " for queue size of ") + toString(queueSize)) + ". Transfer more or wait"))
109142
110143
111144 let stakingContractAddress = match getString(this, stakingContractAddressKey) {
139172 }
140173
141174
175+func mkChainMetaEntry (chainId,newChainHeight,blockHashHex) = StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex))
176+
177+
142178 let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0)
143179
144-let $t049114977 = chainMeta(mainChainId)
180+let $t064236489 = chainMeta(mainChainId)
145181
146-let mainChainHeight = $t049114977._1
182+let mainChainHeight = $t064236489._1
147183
148-let mainChainLastBlock = $t049114977._2
184+let mainChainLastBlock = $t064236489._2
149185
150186 func epochMeta (epoch) = match getString(epochMetaKey(epoch)) {
151187 case s: String =>
156192 }
157193
158194
159-let $t052085672 = match epochMeta(height) {
195+let $t067207184 = match epochMeta(height) {
160196 case m: (Address, Int, String) =>
161197 m
162198 case _ =>
172208 }
173209 }
174210
175-let thisEpochMiner = $t052085672._1
211+let thisEpochMiner = $t067207184._1
176212
177-let thisEpochRef = $t052085672._2
213+let thisEpochRef = $t067207184._2
178214
179-let thisEpochLastBlock = $t052085672._3
215+let thisEpochLastBlock = $t067207184._3
180216
181217 let allMinersStr = valueOrElse(getString(allMinersKey), "")
182218
194230
195231 func blockMeta (blockId) = {
196232 let meta = getBinaryValue((blockMetaK + blockId))
233+ let metaSize = size(meta)
197234 let blockHeight = toInt(meta)
198235 let blockEpoch = toInt(meta, 8)
199236 let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE)
200237 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- }
238+ let chainId = toInt(meta, ((16 + BLOCK_HASH_SIZE) + ADDRESS_SIZE))
239+ let baseOffset = ((24 + BLOCK_HASH_SIZE) + ADDRESS_SIZE)
240+ let remainingBytes = (metaSize - baseOffset)
241+ let elToClTransfersRootHash = if ((remainingBytes >= ROOT_HASH_SIZE))
242+ then take(drop(meta, baseOffset), ROOT_HASH_SIZE)
243+ else base58''
244+ let lastClToElTransferIndex = if (if ((remainingBytes == 8))
245+ then true
246+ else (remainingBytes > ROOT_HASH_SIZE))
247+ then toInt(meta, (baseOffset + size(elToClTransfersRootHash)))
248+ else -1
249+ $Tuple7(blockHeight, blockEpoch, blockParent, blockGenerator, chainId, elToClTransfersRootHash, lastClToElTransferIndex)
208250 }
209251
210252
211-func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,blockGenerator,chainId,elToClTransfersRootHashHex) = {
253+func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,blockGenerator,chainId,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
212254 let blockEpochBytes = toBytes(height)
213- let blockMetaBytes = (((((toBytes(blockHeight) + blockEpochBytes) + fromBase16String(blockParentHex)) + blockGenerator.bytes) + toBytes(chainId)) + fromBase16String(elToClTransfersRootHashHex))
214- BinaryEntry((blockMetaK + blockHashHex), blockMetaBytes)
255+ let blockMetaBytes1 = (((((toBytes(blockHeight) + blockEpochBytes) + fromBase16String(blockParentHex)) + blockGenerator.bytes) + toBytes(chainId)) + fromBase16String(elToClTransfersRootHashHex))
256+ let blockMetaBytes2 = if ((clToElTransfersEpoch > height))
257+ then base58''
258+ else toBytes(lastClToElTransferIndex)
259+ BinaryEntry((blockMetaK + blockHashHex), (blockMetaBytes1 + blockMetaBytes2))
215260 }
216261
217262
224269 }
225270
226271
227-let $t073208286 = {
272+let $t0924610212 = {
228273 let hitSource = match lastBlock.vrf {
229274 case vrf: ByteVector =>
230275 vrf
232277 lastBlock.generationSignature
233278 }
234279 func processMiner (prev,miner) = {
235- let $t076187681 = prev
236- let prevDelay = $t076187681._1
237- let prevMiner = $t076187681._2
238- let prevTotalBalance = $t076187681._3
239- let prevMiners = $t076187681._4
280+ let $t095449607 = prev
281+ let prevDelay = $t095449607._1
282+ let prevMiner = $t095449607._2
283+ let prevTotalBalance = $t095449607._3
284+ let prevMiners = $t095449607._4
240285 let minerAddress = addressFromStringValue(miner)
241286 let wavesGenBalance = wavesBalance(minerAddress).generating
242287 let minerBalance = generatingBalance(minerAddress)
266311 $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)
267312 }
268313
269-let computedDelay = $t073208286._1
314+let computedDelay = $t0924610212._1
270315
271-let computedGenerator = $t073208286._2
316+let computedGenerator = $t0924610212._2
272317
273-let computedTotalBalance = $t073208286._3
318+let computedTotalBalance = $t0924610212._3
274319
275-let filteredMiners = $t073208286._4
320+let filteredMiners = $t0924610212._4
276321
277322 func getChainLastBlockId (chainId) = chainMeta(chainId)._2
278323
279324
280-let $t083528487 = blockMeta(mainChainLastBlock)
325+let $t01027810385 = blockMeta(mainChainLastBlock)
281326
282-let mclbIgnored1 = $t083528487._1
327+let mclbIgnored1 = $t01027810385._1
283328
284-let mainChainEpoch = $t083528487._2
329+let mainChainEpoch = $t01027810385._2
285330
286-let mainChainParentHash = $t083528487._3
331+let mainChainParentHash = $t01027810385._3
287332
288-let mainChainGenerator = $t083528487._4
289-
290-let mclbIgnored2 = $t083528487._5
291-
292-let mclbIgnored3 = $t083528487._6
333+let mainChainGenerator = $t01027810385._4
293334
294335 func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = {
295336 let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "")
296337 let halfBalance = (computedTotalBalance / 2)
297338 func step (prev,next) = {
298- let $t088538917 = prev
299- let thisEpoch = $t088538917._1
300- let totalBalance = $t088538917._2
301- let maybeSafeEpoch = $t088538917._3
302- let prevMiners = $t088538917._4
339+ let $t01075110815 = prev
340+ let thisEpoch = $t01075110815._1
341+ let totalBalance = $t01075110815._2
342+ let maybeSafeEpoch = $t01075110815._3
343+ let prevMiners = $t01075110815._4
303344 match maybeSafeEpoch {
304345 case _: Unit =>
305- let $t089759141 = if ((thisEpoch == height))
346+ let $t01087311039 = if ((thisEpoch == height))
306347 then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash)
307348 else value(epochMeta(thisEpoch))
308- let miner = $t089759141._1
309- let prevEpoch = $t089759141._2
310- let lastBlockHash = $t089759141._3
349+ let miner = $t01087311039._1
350+ let prevEpoch = $t01087311039._2
351+ let lastBlockHash = $t01087311039._3
311352 if ((prevEpoch == 0))
312353 then $Tuple4(thisEpoch, totalBalance, lastBlockHash, allMiners)
313354 else {
314- let $t092669468 = if (containsElement(prevMiners, miner))
355+ let $t01116411366 = if (containsElement(prevMiners, miner))
315356 then $Tuple2(totalBalance, prevMiners)
316357 else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners)
317- let newTotalBalance = $t092669468._1
318- let newMiners = $t092669468._2
358+ let newTotalBalance = $t01116411366._1
359+ let newMiners = $t01116411366._2
319360 if ((newTotalBalance > halfBalance))
320361 then $Tuple4(thisEpoch, newTotalBalance, lastBlockHash, allMiners)
321362 else $Tuple4(prevEpoch, newTotalBalance, unit, newMiners)
325366 }
326367 }
327368
328- let $t097019834 = {
369+ let $t01159911732 = {
329370 let $l = (offsets_100 ++ offsets_100)
330371 let $s = size($l)
331372 let $acc0 = $Tuple4(height, 0, unit, nil)
339380
340381 $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)
341382 }
342- let fallbackEpoch = $t097019834._1
343- let totalBalance = $t097019834._2
344- let finalizedBlockHashOpt = $t097019834._3
345- let miners = $t097019834._4
383+ let fallbackEpoch = $t01159911732._1
384+ let totalBalance = $t01159911732._2
385+ let finalizedBlockHashOpt = $t01159911732._3
386+ let miners = $t01159911732._4
346387 match finalizedBlockHashOpt {
347388 case finalizedBlockHash: String =>
348389 finalizedBlockHash
354395
355396 func supportingBalance (chainId) = {
356397 func addBalance (acc,generatorStr) = {
357- let $t01010410140 = acc
358- let totalBalance = $t01010410140._1
359- let generators = $t01010410140._2
398+ let $t01200212038 = acc
399+ let totalBalance = $t01200212038._1
400+ let generators = $t01200212038._2
360401 let generator = addressFromStringValue(generatorStr)
361402 if (containsElement(generators, generator))
362403 then acc
367408 }
368409
369410 let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP)
370- let $t01046210527 = {
411+ let $t01236012425 = {
371412 let $l = allGenerators
372413 let $s = size($l)
373414 let $acc0 = $Tuple2(0, nil)
381422
382423 $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)
383424 }
384- let balance = $t01046210527._1
385- let _g = $t01046210527._2
425+ let balance = $t01236012425._1
426+ let _g = $t01236012425._2
386427 balance
387428 }
388429
490531
491532
492533 @Callable(i)
493-func appendBlock (blockHashHex,referenceHex) = {
494- let checkVersion = requireElToClTransfersDisabled()
495- if ((checkVersion == checkVersion))
534+func appendBlock_v2 (blockHashHex,referenceHex,elToClTransfersRootHashHex) = {
535+ let checkClToEl = requireClToElTransfersDisabled()
536+ if ((checkClToEl == checkClToEl))
496537 then if ((thisEpochMiner != i.originCaller))
497538 then match thisEpochMiner {
498539 case epochMiner: Address =>
502543 }
503544 else {
504545 let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
505- let $t01464414695 = chainMeta(chainId)
506- let chainHeight = $t01464414695._1
507- let lastBlockId = $t01464414695._2
546+ let $t01658216633 = chainMeta(chainId)
547+ let chainHeight = $t01658216633._1
548+ let lastBlockId = $t01658216633._2
508549 let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
509550 if ((checkReference == checkReference))
510551 then {
511552 let newChainHeight = (chainHeight + 1)
512- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes)
513553 let checkBlockHash = validateBlockHash(blockHashHex)
514554 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))]
555+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex, -1), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
516556 else throw("Strict value is not equal to itself.")
517557 }
518558 else throw("Strict value is not equal to itself.")
523563
524564
525565 @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")
566+func appendBlock_v3 (blockHashHex,referenceHex,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
567+ let checkElToCl = requireClToElTransfersEnabled()
568+ if ((checkElToCl == checkElToCl))
569+ then {
570+ let checkCaller = if ((thisEpochMiner == i.originCaller))
571+ then true
572+ else match thisEpochMiner {
573+ case epochMiner: Address =>
574+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
575+ case _ =>
576+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
577+ }
578+ if ((checkCaller == checkCaller))
579+ then {
580+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
581+ let $t01786017911 = chainMeta(chainId)
582+ let chainHeight = $t01786017911._1
583+ let lastBlockId = $t01786017911._2
584+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
585+ if ((checkReference == checkReference))
586+ then {
587+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, false)
588+ if ((checkTransfers == checkTransfers))
589+ then {
590+ let newChainHeight = (chainHeight + 1)
591+ let checkBlockHash = validateBlockHash(blockHashHex)
592+ if ((checkBlockHash == checkBlockHash))
593+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
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+ else throw("Strict value is not equal to itself.")
535601 }
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.")
551- }
552602 else throw("Strict value is not equal to itself.")
553603 }
554604
555605
556606
557607 @Callable(i)
558-func extendMainChain (blockHashHex,referenceHex,epoch) = {
559- let checkVersion = requireElToClTransfersDisabled()
560- if ((checkVersion == checkVersion))
608+func extendMainChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
609+ let checkClToEl = requireClToElTransfersDisabled()
610+ if ((checkClToEl == checkClToEl))
561611 then {
562612 let checkBlockHash = validateBlockHash(blockHashHex)
563613 if ((checkBlockHash == checkBlockHash))
582632 }
583633 let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
584634 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)
635+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex, -1), mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
587636 }
588637 else throw("Strict value is not equal to itself.")
589638 }
601650
602651
603652 @Callable(i)
604-func extendMainChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
605- let checkVersion = requireElToClTransfersEnabled()
606- if ((checkVersion == checkVersion))
653+func extendMainChain_v3 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
654+ let checkElToCl = requireClToElTransfersEnabled()
655+ if ((checkElToCl == checkElToCl))
607656 then {
608657 let checkBlockHash = validateBlockHash(blockHashHex)
609658 if ((checkBlockHash == checkBlockHash))
620669 let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
621670 if ((checkReference == checkReference))
622671 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)
672+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, true)
673+ if ((checkTransfers == checkTransfers))
674+ then {
675+ let thisEpochMeta = match epochMeta(height) {
676+ case _: Unit =>
677+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
678+ case other =>
679+ throw("Epoch already started")
680+ }
681+ if ((thisEpochMeta == thisEpochMeta))
682+ then {
683+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
684+ let newChainHeight = (mainChainHeight + 1)
685+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex, lastClToElTransferIndex), mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
632690 }
633691 else throw("Strict value is not equal to itself.")
634692 }
646704
647705
648706 @Callable(i)
649-func startAltChain (blockHashHex,referenceHex,epoch) = {
650- let checkVersion = requireElToClTransfersDisabled()
651- if ((checkVersion == checkVersion))
707+func startAltChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
708+ let checkClToEl = requireClToElTransfersDisabled()
709+ if ((checkClToEl == checkClToEl))
652710 then {
653711 let checkBlockHash = validateBlockHash(blockHashHex)
654712 if ((checkBlockHash == checkBlockHash))
659717 let checkGenerator = ensureMiningEpoch(i.originCaller)
660718 if ((checkGenerator == checkGenerator))
661719 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
720+ let $t02180521883 = blockMeta(referenceHex)
721+ let refChainHeight = $t02180521883._1
722+ let refEpoch = $t02180521883._2
723+ let refRef = $t02180521883._3
724+ let refGenerator = $t02180521883._4
669725 let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
670726 let epochRef = if ((refEpoch >= finalizedEpoch))
671727 then refEpoch
675731 then {
676732 let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
677733 let newChainHeight = (blockMeta(referenceHex)._1 + 1)
678- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
679734 let thisEpochMeta = match epochMeta(height) {
680735 case _: Unit =>
681736 StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
682737 case other =>
683738 throw("Epoch already started")
684739 }
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)]
740+[thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex, -1), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), mkChainMetaEntry(newChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
686741 }
687742 else throw("Strict value is not equal to itself.")
688743 }
698753
699754
700755 @Callable(i)
701-func startAltChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
702- let checkVersion = requireElToClTransfersEnabled()
703- if ((checkVersion == checkVersion))
756+func startAltChain_v3 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
757+ let checkElToCl = requireClToElTransfersEnabled()
758+ if ((checkElToCl == checkElToCl))
704759 then {
705760 let checkBlockHash = validateBlockHash(blockHashHex)
706761 if ((checkBlockHash == checkBlockHash))
711766 let checkGenerator = ensureMiningEpoch(i.originCaller)
712767 if ((checkGenerator == checkGenerator))
713768 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
769+ let $t02364123763 = blockMeta(referenceHex)
770+ let refChainHeight = $t02364123763._1
771+ let refEpoch = $t02364123763._2
772+ let refRef = $t02364123763._3
773+ let refGenerator = $t02364123763._4
774+ let refIgnored5 = $t02364123763._5
775+ let refIgnored6 = $t02364123763._6
776+ let refTransferIndex = $t02364123763._7
721777 let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
722778 let epochRef = if ((refEpoch >= finalizedEpoch))
723779 then refEpoch
724- else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
780+ else throw((((("Can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
725781 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
726782 if ((checkChain == checkChain))
727783 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)]
784+ let checkTransfers = ensureCorrectTransfers(refTransferIndex, lastClToElTransferIndex, true)
785+ if ((checkTransfers == checkTransfers))
786+ then {
787+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
788+ let newChainHeight = (refChainHeight + 1)
789+ let thisEpochMeta = match epochMeta(height) {
790+ case _: Unit =>
791+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
792+ case other =>
793+ throw("Epoch already started")
794+ }
795+[thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex, lastClToElTransferIndex), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), mkChainMetaEntry(newChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
796+ }
797+ else throw("Strict value is not equal to itself.")
737798 }
738799 else throw("Strict value is not equal to itself.")
739800 }
749810
750811
751812 @Callable(i)
752-func extendAltChain (chainId,blockHashHex,referenceHex,epoch) = {
753- let checkVersion = requireElToClTransfersDisabled()
754- if ((checkVersion == checkVersion))
813+func extendAltChain_v2 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
814+ let checkClToEl = requireClToElTransfersDisabled()
815+ if ((checkClToEl == checkClToEl))
755816 then {
756817 let checkBlockHash = validateBlockHash(blockHashHex)
757818 if ((checkBlockHash == checkBlockHash))
766827 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
767828 if ((checkChain == checkChain))
768829 then {
769- let $t02395524009 = chainMeta(chainId)
770- let chainHeight = $t02395524009._1
771- let chainLastBlock = $t02395524009._2
830+ let $t02613726191 = chainMeta(chainId)
831+ let chainHeight = $t02613726191._1
832+ let chainLastBlock = $t02613726191._2
772833 let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
773834 if ((checkReference == checkReference))
774835 then {
792853 else false)
793854 then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
794855 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)
856+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex, -1), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
797857 }
798858 else throw("Strict value is not equal to itself.")
799859 }
811871
812872
813873 @Callable(i)
814-func extendAltChain_v2 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
815- let checkVersion = requireElToClTransfersEnabled()
816- if ((checkVersion == checkVersion))
874+func extendAltChain_v3 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
875+ let checkElToCl = requireClToElTransfersEnabled()
876+ if ((checkElToCl == checkElToCl))
817877 then {
818878 let checkBlockHash = validateBlockHash(blockHashHex)
819879 if ((checkBlockHash == checkBlockHash))
828888 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
829889 if ((checkChain == checkChain))
830890 then {
831- let $t02661226666 = chainMeta(chainId)
832- let chainHeight = $t02661226666._1
833- let chainLastBlock = $t02661226666._2
891+ let $t02873528789 = chainMeta(chainId)
892+ let chainHeight = $t02873528789._1
893+ let chainLastBlock = $t02873528789._2
834894 let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
835895 if ((checkReference == checkReference))
836896 then {
837- let newChainHeight = (chainHeight + 1)
838- let prevEpoch = blockMeta(referenceHex)._2
839- let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
897+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, true)
898+ if ((checkTransfers == checkTransfers))
840899 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)
900+ let newChainHeight = (chainHeight + 1)
901+ let prevEpoch = blockMeta(referenceHex)._2
902+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
903+ then {
904+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
905+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
906+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
907+ }
908+ else nil
909+ let thisEpochMeta = match epochMeta(height) {
910+ case _: Unit =>
911+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
912+ case other =>
913+ throw("Epoch already started")
844914 }
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)
915+ if ((thisEpochMeta == thisEpochMeta))
916+ then {
917+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
918+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
919+ else false)
920+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
921+ else nil
922+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
923+ }
924+ else throw("Strict value is not equal to itself.")
925+ }
926+ else throw("Strict value is not equal to itself.")
858927 }
859928 else throw("Strict value is not equal to itself.")
860929 }
873942
874943 @Callable(i)
875944 func join (rewardAddress) = {
876- func checkRewardAddress (address) = match getBinary(minerPkKey(address)) {
945+ func ensureNotOverrideOtherMinerPk (elAddressHex) = match getBinary(minerPkKey(elAddressHex)) {
877946 case pk: ByteVector =>
878947 if ((pk == i.originCallerPublicKey))
879948 then unit
880- else throw(((("L2 miner address " + address) + " is already linked with ") + toBase58String(pk)))
949+ else throw(((("EL miner address " + elAddressHex) + " is already linked with ") + toBase58String(pk)))
881950 case _ =>
882951 unit
883952 }
914983 else {
915984 let newMiner = toString(i.originCaller)
916985 let rewardAddressHex = toBase16String(rewardAddress)
917- let check = checkRewardAddress(rewardAddressHex)
986+ let check = ensureNotOverrideOtherMinerPk(rewardAddressHex)
918987 if ((check == check))
919988 then {
920989 let newMiners = if ((size(allMiners) == 0))
9621031 let prevRewardAddress = valueOrErrorMessage(getString(this, rewardAddrKey), "miner has never joined")
9631032 if ((thisEpochMiner == i.originCaller))
9641033 then throw("designated miner can't leave")
965- else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP)), DeleteEntry(rewardAddrKey), DeleteEntry(minerPkKey(prevRewardAddress))]
1034+ else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP))]
1035+ }
1036+
1037+
1038+
1039+@Callable(i)
1040+func transfer (destElAddressHex) = {
1041+ let checkClToEl = requireClToElTransfersEnabled()
1042+ if ((checkClToEl == checkClToEl))
1043+ then {
1044+ let checkPayment = if ((size(i.payments) == 1))
1045+ then true
1046+ else throw(("Expected one payment as a transfer amount, got " + toString(size(i.payments))))
1047+ if ((checkPayment == checkPayment))
1048+ then {
1049+ let tokenIdStr = getStringValue(tokenIdKey)
1050+ let tokenId = fromBase58String(tokenIdStr)
1051+ let t = i.payments[0]
1052+ let checkAssetId = match t.assetId {
1053+ case assetId: ByteVector =>
1054+ if ((assetId == tokenId))
1055+ then true
1056+ else throw(((("Expected " + tokenIdStr) + " in the payment, got ") + toBase58String(assetId)))
1057+ case _ =>
1058+ throw((("Expected " + tokenIdStr) + " in the payment, got Waves"))
1059+ }
1060+ if ((checkAssetId == checkAssetId))
1061+ then {
1062+ let lastIndex = blockMeta(mainChainLastBlock)._7
1063+ let queueSize = ((nativeTransfersCount - lastIndex) + 1)
1064+ let checkQueueLimit = if ((160 > queueSize))
1065+ then amountGtEq(t, 1000000, queueSize)
1066+ else if ((1600 > queueSize))
1067+ then amountGtEq(t, 10000000, queueSize)
1068+ else if ((3200 > queueSize))
1069+ then amountGtEq(t, 100000000, queueSize)
1070+ else if ((6400 > queueSize))
1071+ then amountGtEq(t, 1000000000, queueSize)
1072+ else throw((("Transfers denied for queue size of " + toString(queueSize)) + ". Wait until current transfers processed"))
1073+ if ((checkQueueLimit == checkQueueLimit))
1074+ then [IntegerEntry(nativeTransfersCountKey, (nativeTransfersCount + 1)), mkNativeTransferEntry(nativeTransfersCount, destElAddressHex, t.amount), Burn(tokenId, t.amount)]
1075+ else throw("Strict value is not equal to itself.")
1076+ }
1077+ else throw("Strict value is not equal to itself.")
1078+ }
1079+ else throw("Strict value is not equal to itself.")
1080+ }
1081+ else throw("Strict value is not equal to itself.")
9661082 }
9671083
9681084
9691085
9701086 @Callable(i)
9711087 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"))
1088+ let withdrawBlockMeta = blockMeta(blockHashHex)
1089+ let withdrawBlockHeight = withdrawBlockMeta._1
1090+ let finalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
1091+ let mainChainLastBlockHeight = blockMeta(mainChainLastBlock)._1
1092+ if ((withdrawBlockHeight > finalizedBlockHeight))
1093+ then throw(((("EL block #" + toString(withdrawBlockHeight)) + " is not finalized. The current finalized is #") + toString(finalizedBlockHeight)))
1094+ else {
1095+ let withdrawBlockChainId = withdrawBlockMeta._5
1096+ let isMainChain = (withdrawBlockChainId == mainChainId)
1097+ let relatesToMainChain = match getInteger(chainForkedHeightKey(withdrawBlockChainId)) {
1098+ case forkedHeight: Int =>
1099+ (forkedHeight > withdrawBlockHeight)
1100+ case _ =>
1101+ throw((((blockHashHex + " is on an alternative chain #") + toString(withdrawBlockChainId)) + " that was not approved by majority. Wait for some blocks"))
1102+ }
1103+ if (if (isMainChain)
1104+ then true
1105+ else relatesToMainChain)
1106+ then {
1107+ let recipient = i.originCaller
1108+ let recipientPkHash = take(drop(recipient.bytes, 2), PUBLIC_KEY_HASH_SIZE)
1109+ let zeroAmountBytes = base58'11111111111111111111111111111111111111111111'
1110+ let amountBytes = toBytes(amount)
1111+ let elEventData = ((recipientPkHash + take(zeroAmountBytes, (size(zeroAmountBytes) - size(amountBytes)))) + amountBytes)
1112+ let elEventDataDigest = blake2b256_16Kb(elEventData)
1113+ let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock)
1114+ let expectedRootHash = withdrawBlockMeta._6
1115+ if ((calculatedRootHash == expectedRootHash))
1116+ then {
1117+ let tokenId = fromBase58String(getStringValue(tokenIdKey))
1118+ let transfersKey = blockElToClTransfersKey(blockHashHex)
1119+[Reissue(tokenId, amount, true), ScriptTransfer(recipient, amount, tokenId), StringEntry(transfersKey, setOrFail(valueOrElse(getString(transfersKey), ""), transferIndexInBlock))]
1120+ }
1121+ else throw((((((("Expected root hash: " + toBase16String(expectedRootHash)) + ", got: ") + toBase16String(calculatedRootHash)) + ". Event data digest: ") + toBase64String(elEventDataDigest)) + ". Check your withdraw arguments"))
9891122 }
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- }
1123+ else throw((("Expected " + blockHashHex) + " to be either on the main chain or relate to it"))
10121124 }
1013- else throw("Strict value is not equal to itself.")
10141125 }
10151126
10161127
10281139 let genesisBlockReferenceHash = "0000000000000000000000000000000000000000000000000000000000000000"
10291140 let issue = Issue("UNIT0", "Native token", 0, 8, true)
10301141 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))]
1142+ let genesisBlockMeta = ((((((toBytes(0) + toBytes(height)) + fromBase16String(genesisBlockReferenceHash)) + genesisMinerAddress.bytes) + toBytes(0)) + base58'') + toBytes(-1))
1143+[BinaryEntry((blockMetaK + genesisBlockHashHex), genesisBlockMeta), StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(stakingContractAddressKey, stakingContractAddressB58), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, ("0x" + elBridgeAddressHex)), IntegerEntry(clToElTransfersEpochKey, 0)]
10321144 }
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")
1039- else {
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))]
1043- }
10441145
10451146
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
1515
1616 let PUBLIC_KEY_HASH_SIZE = 20
17+
18+let ROOT_HASH_SIZE = 32
19+
20+let MAX_CL_TO_EL_TRANSFERS = 16
1721
1822 let zeroesStr = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
1923
2024 let thisEpochDataKey = "thisEpochData"
2125
2226 let allMinersKey = "allMiners"
2327
2428 let mainChainIdKey = "mainChainId"
2529
2630 let lastChainIdKey = "lastChainId"
2731
2832 let firstValidAltChainIdKey = "firstValidAltChainId"
2933
3034 let minerRewardKey = "minerReward"
3135
3236 let stakingContractAddressKey = "stakingContractAddress"
3337
3438 let blockMetaK = "block_0x"
3539
3640 let finalizedBlockKey = "finalizedBlock"
3741
3842 let tokenIdKey = "tokenId"
3943
4044 let elBridgeAddressKey = "elBridgeAddress"
4145
42-let prevRandaoHeightKey = "prevRandaoHeight"
46+let nativeTransfersCountKey = "nativeTransfersCount"
4347
44-let elToClTransfersEpochKey = "elToClTransfersEpoch"
48+let clToElTransfersEpochKey = "clToElTransfersEpoch"
4549
4650 func pad (i) = {
4751 let s = toString(i)
4852 match size(s) {
4953 case _ =>
5054 if ((1 == $match0))
5155 then ("0000000" + s)
5256 else if ((2 == $match0))
5357 then ("000000" + s)
5458 else if ((3 == $match0))
5559 then ("00000" + s)
5660 else if ((4 == $match0))
5761 then ("0000" + s)
5862 else if ((5 == $match0))
5963 then ("000" + s)
6064 else if ((6 == $match0))
6165 then ("00" + s)
6266 else if ((7 == $match0))
6367 then ("0" + s)
6468 else s
6569 }
6670 }
6771
6872
6973 func blockElToClTransfersKey (blockHashHex) = ("elToClTransfers_0x" + blockHashHex)
7074
7175
7276 func epochMetaKey (epoch) = ("epoch_" + pad(epoch))
7377
7478
7579 func chainFirstBlockIdKey (chainId) = (("chain" + toString(chainId)) + "FirstBlock")
7680
7781
7882 func chainMetaKey (chainId) = ("chain_" + pad(chainId))
7983
8084
8185 func chainLastHeightKey (chainId,miner) = ((("chain_" + pad(chainId)) + "_") + toString(miner))
8286
8387
8488 func chainForkedHeightKey (chainId) = (("chain_" + pad(chainId)) + "ForkedHeight")
8589
8690
8791 func supportersKey (chainId) = (("chain" + toString(chainId)) + "Supporters")
8892
8993
9094 func minerRewardAddressKey (minerAddr) = (("miner_" + minerAddr) + "_RewardAddress")
9195
9296
9397 func minerPkKey (rewardAddress) = (("miner_0x" + rewardAddress) + "_PK")
9498
9599
96100 func minerChainIdKey (miner) = (("miner_" + toString(miner)) + "_ChainId")
97101
98102
99-let elToClTransfersEpoch = valueOrElse(getInteger(this, elToClTransfersEpochKey), INT_MAX)
103+let nativeTransfersCount = valueOrElse(getInteger(this, nativeTransfersCountKey), 0)
100104
101-func requireElToClTransfersDisabled () = if ((elToClTransfersEpoch > height))
102- then unit
103- else throw((("EL to CL transfers activated on epoch #" + toString(height)) + ". Upgrade your client"))
105+func nativeTransferKey (index) = ("nativeTransfer_" + toString(index))
104106
105107
106-func requireElToClTransfersEnabled () = if ((height >= elToClTransfersEpoch))
108+func mkNativeTransferEntry (index,destElAddressHex,amount) = StringEntry(nativeTransferKey(index), ((("0x" + destElAddressHex) + SEP) + toString(amount)))
109+
110+
111+let clToElTransfersEpoch = valueOrElse(getInteger(this, clToElTransfersEpochKey), INT_MAX)
112+
113+func requireClToElTransfersDisabled () = if ((clToElTransfersEpoch > height))
107114 then unit
108- else throw(((("EL to CL transfers haven't activated on epoch #" + toString(height)) + ". Wait for activation on #") + toString(elToClTransfersEpoch)))
115+ else throw((("CL to EL transfers activated on epoch #" + toString(height)) + ". Upgrade your client"))
116+
117+
118+func requireClToElTransfersEnabled () = if ((height >= clToElTransfersEpoch))
119+ then unit
120+ else throw(((("CL to EL transfers haven't activated on epoch #" + toString(height)) + ". Wait for activation on #") + toString(clToElTransfersEpoch)))
121+
122+
123+func ensureCorrectTransfers (refTransferIndex,transferIndex,expectReward) = {
124+ let maxTransfers = if (expectReward)
125+ then (MAX_CL_TO_EL_TRANSFERS - 1)
126+ else MAX_CL_TO_EL_TRANSFERS
127+ let actualTransfers = (transferIndex - refTransferIndex)
128+ let checkNumber = if ((actualTransfers > maxTransfers))
129+ then throw(((("Allowed only " + toString(maxTransfers)) + " transfers, got ") + toString(actualTransfers)))
130+ else true
131+ if ((checkNumber == checkNumber))
132+ then if ((transferIndex >= nativeTransfersCount))
133+ then throw(((("Attempt to transfer #" + toString(transferIndex)) + ". Available transfers: ") + toString(nativeTransfersCount)))
134+ else true
135+ else throw("Strict value is not equal to itself.")
136+ }
137+
138+
139+func amountGtEq (t,gtEq,queueSize) = if ((t.amount >= gtEq))
140+ then true
141+ else throw((((((("Transferring amount " + toString(t.amount)) + " should be >= ") + toString(gtEq)) + " for queue size of ") + toString(queueSize)) + ". Transfer more or wait"))
109142
110143
111144 let stakingContractAddress = match getString(this, stakingContractAddressKey) {
112145 case s: String =>
113146 valueOrErrorMessage(addressFromString(s), ("invalid staking contract address: " + s))
114147 case _ =>
115148 Address(getBinaryValue(this, stakingContractAddressKey))
116149 }
117150
118151 func generatingBalance (address) = match getString(stakingContractAddress, ("%s__" + toString(address))) {
119152 case str: String =>
120153 let paramList = split(str, "__")
121154 let prevHeight = parseIntValue(paramList[1])
122155 let prevBalance = parseIntValue(paramList[2])
123156 let nextHeight = parseIntValue(paramList[3])
124157 let nextBalance = parseIntValue(paramList[4])
125158 if ((height >= nextHeight))
126159 then nextBalance
127160 else if ((height >= prevHeight))
128161 then prevBalance
129162 else 0
130163 case _ =>
131164 0
132165 }
133166
134167
135168 func chainMeta (chainId) = {
136169 let s = getStringValue(chainMetaKey(chainId))
137170 let items = split(s, SEP)
138171 $Tuple2(parseIntValue(items[0]), items[1])
139172 }
140173
141174
175+func mkChainMetaEntry (chainId,newChainHeight,blockHashHex) = StringEntry(chainMetaKey(chainId), ((toString(newChainHeight) + SEP) + blockHashHex))
176+
177+
142178 let mainChainId = valueOrElse(getInteger(mainChainIdKey), 0)
143179
144-let $t049114977 = chainMeta(mainChainId)
180+let $t064236489 = chainMeta(mainChainId)
145181
146-let mainChainHeight = $t049114977._1
182+let mainChainHeight = $t064236489._1
147183
148-let mainChainLastBlock = $t049114977._2
184+let mainChainLastBlock = $t064236489._2
149185
150186 func epochMeta (epoch) = match getString(epochMetaKey(epoch)) {
151187 case s: String =>
152188 let fragments = split(s, SEP)
153189 $Tuple3(addressFromStringValue(fragments[0]), parseIntValue(fragments[1]), fragments[2])
154190 case _ =>
155191 unit
156192 }
157193
158194
159-let $t052085672 = match epochMeta(height) {
195+let $t067207184 = match epochMeta(height) {
160196 case m: (Address, Int, String) =>
161197 m
162198 case _ =>
163199 match getString(thisEpochDataKey) {
164200 case rawThisEpochData: String =>
165201 let thisEpochData = split(rawThisEpochData, SEP)
166202 let thisEpoch = parseIntValue(thisEpochData[0])
167203 $Tuple3(if ((thisEpoch == height))
168204 then addressFromStringValue(thisEpochData[1])
169205 else unit, 0, "")
170206 case _ =>
171207 $Tuple3(unit, 0, "")
172208 }
173209 }
174210
175-let thisEpochMiner = $t052085672._1
211+let thisEpochMiner = $t067207184._1
176212
177-let thisEpochRef = $t052085672._2
213+let thisEpochRef = $t067207184._2
178214
179-let thisEpochLastBlock = $t052085672._3
215+let thisEpochLastBlock = $t067207184._3
180216
181217 let allMinersStr = valueOrElse(getString(allMinersKey), "")
182218
183219 let allMiners = match allMinersStr {
184220 case _ =>
185221 if (("" == $match0))
186222 then nil
187223 else if ($isInstanceOf($match0, "String"))
188224 then {
189225 let raw = $match0
190226 split_4C(raw, SEP)
191227 }
192228 else throw("Match error")
193229 }
194230
195231 func blockMeta (blockId) = {
196232 let meta = getBinaryValue((blockMetaK + blockId))
233+ let metaSize = size(meta)
197234 let blockHeight = toInt(meta)
198235 let blockEpoch = toInt(meta, 8)
199236 let blockParent = take(drop(meta, 16), BLOCK_HASH_SIZE)
200237 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- }
238+ let chainId = toInt(meta, ((16 + BLOCK_HASH_SIZE) + ADDRESS_SIZE))
239+ let baseOffset = ((24 + BLOCK_HASH_SIZE) + ADDRESS_SIZE)
240+ let remainingBytes = (metaSize - baseOffset)
241+ let elToClTransfersRootHash = if ((remainingBytes >= ROOT_HASH_SIZE))
242+ then take(drop(meta, baseOffset), ROOT_HASH_SIZE)
243+ else base58''
244+ let lastClToElTransferIndex = if (if ((remainingBytes == 8))
245+ then true
246+ else (remainingBytes > ROOT_HASH_SIZE))
247+ then toInt(meta, (baseOffset + size(elToClTransfersRootHash)))
248+ else -1
249+ $Tuple7(blockHeight, blockEpoch, blockParent, blockGenerator, chainId, elToClTransfersRootHash, lastClToElTransferIndex)
208250 }
209251
210252
211-func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,blockGenerator,chainId,elToClTransfersRootHashHex) = {
253+func mkBlockMetaEntry (blockHashHex,blockHeight,blockParentHex,blockGenerator,chainId,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
212254 let blockEpochBytes = toBytes(height)
213- let blockMetaBytes = (((((toBytes(blockHeight) + blockEpochBytes) + fromBase16String(blockParentHex)) + blockGenerator.bytes) + toBytes(chainId)) + fromBase16String(elToClTransfersRootHashHex))
214- BinaryEntry((blockMetaK + blockHashHex), blockMetaBytes)
255+ let blockMetaBytes1 = (((((toBytes(blockHeight) + blockEpochBytes) + fromBase16String(blockParentHex)) + blockGenerator.bytes) + toBytes(chainId)) + fromBase16String(elToClTransfersRootHashHex))
256+ let blockMetaBytes2 = if ((clToElTransfersEpoch > height))
257+ then base58''
258+ else toBytes(lastClToElTransferIndex)
259+ BinaryEntry((blockMetaK + blockHashHex), (blockMetaBytes1 + blockMetaBytes2))
215260 }
216261
217262
218263 func lastHeightBy (miner,chainId) = match getInteger(chainLastHeightKey(chainId, miner)) {
219264 case h: Int =>
220265 h
221266 case _ =>
222267 let blockHash = getStringValue(((("chain" + toString(chainId)) + "LastMinedBy") + toString(miner)))
223268 blockMeta(blockHash)._1
224269 }
225270
226271
227-let $t073208286 = {
272+let $t0924610212 = {
228273 let hitSource = match lastBlock.vrf {
229274 case vrf: ByteVector =>
230275 vrf
231276 case _ =>
232277 lastBlock.generationSignature
233278 }
234279 func processMiner (prev,miner) = {
235- let $t076187681 = prev
236- let prevDelay = $t076187681._1
237- let prevMiner = $t076187681._2
238- let prevTotalBalance = $t076187681._3
239- let prevMiners = $t076187681._4
280+ let $t095449607 = prev
281+ let prevDelay = $t095449607._1
282+ let prevMiner = $t095449607._2
283+ let prevTotalBalance = $t095449607._3
284+ let prevMiners = $t095449607._4
240285 let minerAddress = addressFromStringValue(miner)
241286 let wavesGenBalance = wavesBalance(minerAddress).generating
242287 let minerBalance = generatingBalance(minerAddress)
243288 if (if ((MIN_BALANCE > wavesGenBalance))
244289 then true
245290 else (0 >= minerBalance))
246291 then prev
247292 else {
248293 let nextDelay = calculateDelay(minerAddress, minerBalance)
249294 if ((prevDelay > nextDelay))
250295 then $Tuple4(nextDelay, miner, (prevTotalBalance + minerBalance), (prevMiners :+ miner))
251296 else $Tuple4(prevDelay, prevMiner, (prevTotalBalance + minerBalance), (prevMiners :+ miner))
252297 }
253298 }
254299
255300 let $l = allMiners
256301 let $s = size($l)
257302 let $acc0 = $Tuple4(INT_MAX, "", 0, nil)
258303 func $f0_1 ($a,$i) = if (($i >= $s))
259304 then $a
260305 else processMiner($a, $l[$i])
261306
262307 func $f0_2 ($a,$i) = if (($i >= $s))
263308 then $a
264309 else throw("List size exceeds 50")
265310
266311 $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)
267312 }
268313
269-let computedDelay = $t073208286._1
314+let computedDelay = $t0924610212._1
270315
271-let computedGenerator = $t073208286._2
316+let computedGenerator = $t0924610212._2
272317
273-let computedTotalBalance = $t073208286._3
318+let computedTotalBalance = $t0924610212._3
274319
275-let filteredMiners = $t073208286._4
320+let filteredMiners = $t0924610212._4
276321
277322 func getChainLastBlockId (chainId) = chainMeta(chainId)._2
278323
279324
280-let $t083528487 = blockMeta(mainChainLastBlock)
325+let $t01027810385 = blockMeta(mainChainLastBlock)
281326
282-let mclbIgnored1 = $t083528487._1
327+let mclbIgnored1 = $t01027810385._1
283328
284-let mainChainEpoch = $t083528487._2
329+let mainChainEpoch = $t01027810385._2
285330
286-let mainChainParentHash = $t083528487._3
331+let mainChainParentHash = $t01027810385._3
287332
288-let mainChainGenerator = $t083528487._4
289-
290-let mclbIgnored2 = $t083528487._5
291-
292-let mclbIgnored3 = $t083528487._6
333+let mainChainGenerator = $t01027810385._4
293334
294335 func calculateFinalizedBlockHash (curMiner,curPrevEpoch,curLastBlockHash) = {
295336 let offsets_100 = split_4C("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", "")
296337 let halfBalance = (computedTotalBalance / 2)
297338 func step (prev,next) = {
298- let $t088538917 = prev
299- let thisEpoch = $t088538917._1
300- let totalBalance = $t088538917._2
301- let maybeSafeEpoch = $t088538917._3
302- let prevMiners = $t088538917._4
339+ let $t01075110815 = prev
340+ let thisEpoch = $t01075110815._1
341+ let totalBalance = $t01075110815._2
342+ let maybeSafeEpoch = $t01075110815._3
343+ let prevMiners = $t01075110815._4
303344 match maybeSafeEpoch {
304345 case _: Unit =>
305- let $t089759141 = if ((thisEpoch == height))
346+ let $t01087311039 = if ((thisEpoch == height))
306347 then $Tuple3(curMiner, curPrevEpoch, curLastBlockHash)
307348 else value(epochMeta(thisEpoch))
308- let miner = $t089759141._1
309- let prevEpoch = $t089759141._2
310- let lastBlockHash = $t089759141._3
349+ let miner = $t01087311039._1
350+ let prevEpoch = $t01087311039._2
351+ let lastBlockHash = $t01087311039._3
311352 if ((prevEpoch == 0))
312353 then $Tuple4(thisEpoch, totalBalance, lastBlockHash, allMiners)
313354 else {
314- let $t092669468 = if (containsElement(prevMiners, miner))
355+ let $t01116411366 = if (containsElement(prevMiners, miner))
315356 then $Tuple2(totalBalance, prevMiners)
316357 else $Tuple2((totalBalance + generatingBalance(miner)), miner :: prevMiners)
317- let newTotalBalance = $t092669468._1
318- let newMiners = $t092669468._2
358+ let newTotalBalance = $t01116411366._1
359+ let newMiners = $t01116411366._2
319360 if ((newTotalBalance > halfBalance))
320361 then $Tuple4(thisEpoch, newTotalBalance, lastBlockHash, allMiners)
321362 else $Tuple4(prevEpoch, newTotalBalance, unit, newMiners)
322363 }
323364 case _ =>
324365 prev
325366 }
326367 }
327368
328- let $t097019834 = {
369+ let $t01159911732 = {
329370 let $l = (offsets_100 ++ offsets_100)
330371 let $s = size($l)
331372 let $acc0 = $Tuple4(height, 0, unit, nil)
332373 func $f0_1 ($a,$i) = if (($i >= $s))
333374 then $a
334375 else step($a, $l[$i])
335376
336377 func $f0_2 ($a,$i) = if (($i >= $s))
337378 then $a
338379 else throw("List size exceeds 200")
339380
340381 $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)
341382 }
342- let fallbackEpoch = $t097019834._1
343- let totalBalance = $t097019834._2
344- let finalizedBlockHashOpt = $t097019834._3
345- let miners = $t097019834._4
383+ let fallbackEpoch = $t01159911732._1
384+ let totalBalance = $t01159911732._2
385+ let finalizedBlockHashOpt = $t01159911732._3
386+ let miners = $t01159911732._4
346387 match finalizedBlockHashOpt {
347388 case finalizedBlockHash: String =>
348389 finalizedBlockHash
349390 case _ =>
350391 value(epochMeta(fallbackEpoch))._3
351392 }
352393 }
353394
354395
355396 func supportingBalance (chainId) = {
356397 func addBalance (acc,generatorStr) = {
357- let $t01010410140 = acc
358- let totalBalance = $t01010410140._1
359- let generators = $t01010410140._2
398+ let $t01200212038 = acc
399+ let totalBalance = $t01200212038._1
400+ let generators = $t01200212038._2
360401 let generator = addressFromStringValue(generatorStr)
361402 if (containsElement(generators, generator))
362403 then acc
363404 else {
364405 let balance = generatingBalance(generator)
365406 $Tuple2((totalBalance + balance), (generators :+ generator))
366407 }
367408 }
368409
369410 let allGenerators = split_4C(getStringValue(supportersKey(chainId)), SEP)
370- let $t01046210527 = {
411+ let $t01236012425 = {
371412 let $l = allGenerators
372413 let $s = size($l)
373414 let $acc0 = $Tuple2(0, nil)
374415 func $f0_1 ($a,$i) = if (($i >= $s))
375416 then $a
376417 else addBalance($a, $l[$i])
377418
378419 func $f0_2 ($a,$i) = if (($i >= $s))
379420 then $a
380421 else throw("List size exceeds 100")
381422
382423 $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)
383424 }
384- let balance = $t01046210527._1
385- let _g = $t01046210527._2
425+ let balance = $t01236012425._1
426+ let _g = $t01236012425._2
386427 balance
387428 }
388429
389430
390431 func isContractSetup () = isDefined(getInteger(minerRewardKey))
391432
392433
393434 func ensureMiningEpoch (generator) = if ((toString(generator) != computedGenerator))
394435 then throw(((((toBase58String(generator.bytes) + " is not allowed to mine in ") + toString(height)) + " epoch. Expected ") + computedGenerator))
395436 else unit
396437
397438
398439 func isReferenceCorrect (reference,lastBlock) = if ((reference == lastBlock))
399440 then unit
400441 else throw(((("Expected a reference to the chain last block: 0x" + lastBlock) + ". Got: 0x") + reference))
401442
402443
403444 func chainIsInactive (chainId) = {
404445 let firstBlockId = getStringValue(chainFirstBlockIdKey(chainId))
405446 let firstValidAltChainId = valueOrElse(getInteger(firstValidAltChainIdKey), 0)
406447 if ((firstValidAltChainId > chainId))
407448 then true
408449 else (blockMeta(getStringValue(finalizedBlockKey))._1 > blockMeta(firstBlockId)._1)
409450 }
410451
411452
412453 func minerChainId (miner) = valueOrElse(getInteger(minerChainIdKey(miner)), getInteger(("chainIdOf" + toString(miner))))
413454
414455
415456 func ensureExpectedOrInactiveChain (generator,expectedChainId,checkHeightBlock) = {
416457 let heightIsCorrect = match checkHeightBlock {
417458 case blockHash: String =>
418459 let lastMinedBlockHeight = lastHeightBy(generator, mainChainId)
419460 ((blockMeta(blockHash)._1 + 1) > lastMinedBlockHeight)
420461 case _ =>
421462 true
422463 }
423464 match minerChainId(generator) {
424465 case currentId: Int =>
425466 if (if ((currentId == expectedChainId))
426467 then true
427468 else if (chainIsInactive(currentId))
428469 then heightIsCorrect
429470 else false)
430471 then unit
431472 else throw(("miner is mining other chain " + toString(currentId)))
432473 case _ =>
433474 unit
434475 }
435476 }
436477
437478
438479 func ensureCorrectEpoch (epoch) = if ((epoch == height))
439480 then unit
440481 else throw(((("Expected block from epoch " + toString(height)) + ". Got ") + toString(epoch)))
441482
442483
443484 func addSupporter (chainId,generator) = {
444485 let supportersStr = getStringValue(supportersKey(chainId))
445486 let supporters = split_4C(supportersStr, SEP)
446487 if (containsElement(supporters, toString(generator)))
447488 then nil
448489 else [StringEntry(supportersKey(chainId), ((supportersStr + SEP) + toString(generator)))]
449490 }
450491
451492
452493 func setOrFail (flags,index) = if ((0 > index))
453494 then throw(("Can't withdraw at negative index: " + toString(index)))
454495 else {
455496 let flagsSize = size(flags)
456497 if ((index >= flagsSize))
457498 then {
458499 let addZeroes = (index - flagsSize)
459500 if ((addZeroes > size(zeroesStr)))
460501 then throw((("Can't add " + toString(addZeroes)) + " empty flags. Contact with developers"))
461502 else ((flags + take(zeroesStr, addZeroes)) + "1")
462503 }
463504 else {
464505 let tail = drop(flags, index)
465506 let atIndex = take(tail, 1)
466507 if ((atIndex == "0"))
467508 then ((take(flags, index) + "1") + drop(tail, 1))
468509 else throw((("Transfer #" + toString(index)) + " has been already taken"))
469510 }
470511 }
471512
472513
473514 func validateBlockHash (hexStr) = {
474515 let decodedBytes = fromBase16String(hexStr)
475516 if ((size(decodedBytes) != 32))
476517 then throw("invalid block id length")
477518 else hexStr
478519 }
479520
480521
481522 func getUpdateFinalizedBlockAction (caller,newBlockHashHex,prevEpoch) = {
482523 let curFinalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
483524 let newFinalizedBlockHash = calculateFinalizedBlockHash(caller, prevEpoch, newBlockHashHex)
484525 if (if ((newFinalizedBlockHash == newBlockHashHex))
485526 then true
486527 else (blockMeta(newFinalizedBlockHash)._1 > curFinalizedBlockHeight))
487528 then [StringEntry(finalizedBlockKey, newFinalizedBlockHash)]
488529 else nil
489530 }
490531
491532
492533 @Callable(i)
493-func appendBlock (blockHashHex,referenceHex) = {
494- let checkVersion = requireElToClTransfersDisabled()
495- if ((checkVersion == checkVersion))
534+func appendBlock_v2 (blockHashHex,referenceHex,elToClTransfersRootHashHex) = {
535+ let checkClToEl = requireClToElTransfersDisabled()
536+ if ((checkClToEl == checkClToEl))
496537 then if ((thisEpochMiner != i.originCaller))
497538 then match thisEpochMiner {
498539 case epochMiner: Address =>
499540 throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
500541 case _ =>
501542 throw("not allowed to forge blocks in this epoch, epoch miner is absent")
502543 }
503544 else {
504545 let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
505- let $t01464414695 = chainMeta(chainId)
506- let chainHeight = $t01464414695._1
507- let lastBlockId = $t01464414695._2
546+ let $t01658216633 = chainMeta(chainId)
547+ let chainHeight = $t01658216633._1
548+ let lastBlockId = $t01658216633._2
508549 let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
509550 if ((checkReference == checkReference))
510551 then {
511552 let newChainHeight = (chainHeight + 1)
512- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(lastBlockId)) + i.originCaller.bytes)
513553 let checkBlockHash = validateBlockHash(blockHashHex)
514554 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))]
555+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex, -1), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
516556 else throw("Strict value is not equal to itself.")
517557 }
518558 else throw("Strict value is not equal to itself.")
519559 }
520560 else throw("Strict value is not equal to itself.")
521561 }
522562
523563
524564
525565 @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")
566+func appendBlock_v3 (blockHashHex,referenceHex,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
567+ let checkElToCl = requireClToElTransfersEnabled()
568+ if ((checkElToCl == checkElToCl))
569+ then {
570+ let checkCaller = if ((thisEpochMiner == i.originCaller))
571+ then true
572+ else match thisEpochMiner {
573+ case epochMiner: Address =>
574+ throw(("not allowed to forge blocks in this epoch, expected from " + toString(epochMiner)))
575+ case _ =>
576+ throw("not allowed to forge blocks in this epoch, epoch miner is absent")
577+ }
578+ if ((checkCaller == checkCaller))
579+ then {
580+ let chainId = valueOrElse(minerChainId(i.originCaller), mainChainId)
581+ let $t01786017911 = chainMeta(chainId)
582+ let chainHeight = $t01786017911._1
583+ let lastBlockId = $t01786017911._2
584+ let checkReference = isReferenceCorrect(referenceHex, lastBlockId)
585+ if ((checkReference == checkReference))
586+ then {
587+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, false)
588+ if ((checkTransfers == checkTransfers))
589+ then {
590+ let newChainHeight = (chainHeight + 1)
591+ let checkBlockHash = validateBlockHash(blockHashHex)
592+ if ((checkBlockHash == checkBlockHash))
593+ then [mkBlockMetaEntry(blockHashHex, newChainHeight, lastBlockId, i.originCaller, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), StringEntry(epochMetaKey(height), ((((toString(value(thisEpochMiner)) + SEP) + toString(thisEpochRef)) + SEP) + blockHashHex))]
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+ else throw("Strict value is not equal to itself.")
535601 }
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.")
551- }
552602 else throw("Strict value is not equal to itself.")
553603 }
554604
555605
556606
557607 @Callable(i)
558-func extendMainChain (blockHashHex,referenceHex,epoch) = {
559- let checkVersion = requireElToClTransfersDisabled()
560- if ((checkVersion == checkVersion))
608+func extendMainChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
609+ let checkClToEl = requireClToElTransfersDisabled()
610+ if ((checkClToEl == checkClToEl))
561611 then {
562612 let checkBlockHash = validateBlockHash(blockHashHex)
563613 if ((checkBlockHash == checkBlockHash))
564614 then {
565615 let checkEpoch = ensureCorrectEpoch(epoch)
566616 if ((checkEpoch == checkEpoch))
567617 then {
568618 let checkGenerator = ensureMiningEpoch(i.originCaller)
569619 if ((checkGenerator == checkGenerator))
570620 then {
571621 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
572622 if ((checkChain == checkChain))
573623 then {
574624 let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
575625 if ((checkReference == checkReference))
576626 then {
577627 let thisEpochMeta = match epochMeta(height) {
578628 case _: Unit =>
579629 StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
580630 case other =>
581631 throw("Epoch already started")
582632 }
583633 let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
584634 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)
635+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex, -1), mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
587636 }
588637 else throw("Strict value is not equal to itself.")
589638 }
590639 else throw("Strict value is not equal to itself.")
591640 }
592641 else throw("Strict value is not equal to itself.")
593642 }
594643 else throw("Strict value is not equal to itself.")
595644 }
596645 else throw("Strict value is not equal to itself.")
597646 }
598647 else throw("Strict value is not equal to itself.")
599648 }
600649
601650
602651
603652 @Callable(i)
604-func extendMainChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
605- let checkVersion = requireElToClTransfersEnabled()
606- if ((checkVersion == checkVersion))
653+func extendMainChain_v3 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
654+ let checkElToCl = requireClToElTransfersEnabled()
655+ if ((checkElToCl == checkElToCl))
607656 then {
608657 let checkBlockHash = validateBlockHash(blockHashHex)
609658 if ((checkBlockHash == checkBlockHash))
610659 then {
611660 let checkEpoch = ensureCorrectEpoch(epoch)
612661 if ((checkEpoch == checkEpoch))
613662 then {
614663 let checkGenerator = ensureMiningEpoch(i.originCaller)
615664 if ((checkGenerator == checkGenerator))
616665 then {
617666 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, unit)
618667 if ((checkChain == checkChain))
619668 then {
620669 let checkReference = isReferenceCorrect(referenceHex, mainChainLastBlock)
621670 if ((checkReference == checkReference))
622671 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)
672+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, true)
673+ if ((checkTransfers == checkTransfers))
674+ then {
675+ let thisEpochMeta = match epochMeta(height) {
676+ case _: Unit =>
677+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(mainChainEpoch)) + SEP) + blockHashHex))
678+ case other =>
679+ throw("Epoch already started")
680+ }
681+ if ((thisEpochMeta == thisEpochMeta))
682+ then {
683+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, mainChainEpoch)
684+ let newChainHeight = (mainChainHeight + 1)
685+ ([mkBlockMetaEntry(blockHashHex, newChainHeight, mainChainLastBlock, i.originCaller, mainChainId, elToClTransfersRootHashHex, lastClToElTransferIndex), mkChainMetaEntry(mainChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), mainChainId), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), thisEpochMeta] ++ updateFinalizedBlock)
686+ }
687+ else throw("Strict value is not equal to itself.")
688+ }
689+ else throw("Strict value is not equal to itself.")
632690 }
633691 else throw("Strict value is not equal to itself.")
634692 }
635693 else throw("Strict value is not equal to itself.")
636694 }
637695 else throw("Strict value is not equal to itself.")
638696 }
639697 else throw("Strict value is not equal to itself.")
640698 }
641699 else throw("Strict value is not equal to itself.")
642700 }
643701 else throw("Strict value is not equal to itself.")
644702 }
645703
646704
647705
648706 @Callable(i)
649-func startAltChain (blockHashHex,referenceHex,epoch) = {
650- let checkVersion = requireElToClTransfersDisabled()
651- if ((checkVersion == checkVersion))
707+func startAltChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
708+ let checkClToEl = requireClToElTransfersDisabled()
709+ if ((checkClToEl == checkClToEl))
652710 then {
653711 let checkBlockHash = validateBlockHash(blockHashHex)
654712 if ((checkBlockHash == checkBlockHash))
655713 then {
656714 let checkEpoch = ensureCorrectEpoch(epoch)
657715 if ((checkEpoch == checkEpoch))
658716 then {
659717 let checkGenerator = ensureMiningEpoch(i.originCaller)
660718 if ((checkGenerator == checkGenerator))
661719 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
720+ let $t02180521883 = blockMeta(referenceHex)
721+ let refChainHeight = $t02180521883._1
722+ let refEpoch = $t02180521883._2
723+ let refRef = $t02180521883._3
724+ let refGenerator = $t02180521883._4
669725 let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
670726 let epochRef = if ((refEpoch >= finalizedEpoch))
671727 then refEpoch
672728 else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
673729 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
674730 if ((checkChain == checkChain))
675731 then {
676732 let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
677733 let newChainHeight = (blockMeta(referenceHex)._1 + 1)
678- let newBlockMeta = (((toBytes(newChainHeight) + toBytes(height)) + fromBase16String(referenceHex)) + i.originCaller.bytes)
679734 let thisEpochMeta = match epochMeta(height) {
680735 case _: Unit =>
681736 StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
682737 case other =>
683738 throw("Epoch already started")
684739 }
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)]
740+[thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex, -1), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), mkChainMetaEntry(newChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
686741 }
687742 else throw("Strict value is not equal to itself.")
688743 }
689744 else throw("Strict value is not equal to itself.")
690745 }
691746 else throw("Strict value is not equal to itself.")
692747 }
693748 else throw("Strict value is not equal to itself.")
694749 }
695750 else throw("Strict value is not equal to itself.")
696751 }
697752
698753
699754
700755 @Callable(i)
701-func startAltChain_v2 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
702- let checkVersion = requireElToClTransfersEnabled()
703- if ((checkVersion == checkVersion))
756+func startAltChain_v3 (blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
757+ let checkElToCl = requireClToElTransfersEnabled()
758+ if ((checkElToCl == checkElToCl))
704759 then {
705760 let checkBlockHash = validateBlockHash(blockHashHex)
706761 if ((checkBlockHash == checkBlockHash))
707762 then {
708763 let checkEpoch = ensureCorrectEpoch(epoch)
709764 if ((checkEpoch == checkEpoch))
710765 then {
711766 let checkGenerator = ensureMiningEpoch(i.originCaller)
712767 if ((checkGenerator == checkGenerator))
713768 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
769+ let $t02364123763 = blockMeta(referenceHex)
770+ let refChainHeight = $t02364123763._1
771+ let refEpoch = $t02364123763._2
772+ let refRef = $t02364123763._3
773+ let refGenerator = $t02364123763._4
774+ let refIgnored5 = $t02364123763._5
775+ let refIgnored6 = $t02364123763._6
776+ let refTransferIndex = $t02364123763._7
721777 let finalizedEpoch = blockMeta(getStringValue(finalizedBlockKey))._2
722778 let epochRef = if ((refEpoch >= finalizedEpoch))
723779 then refEpoch
724- else throw((((("can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
780+ else throw((((("Can not start alt chain from epoch " + toString(refEpoch)) + ", epoch ") + toString(finalizedEpoch)) + " is finalized"))
725781 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, mainChainId, referenceHex)
726782 if ((checkChain == checkChain))
727783 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)]
784+ let checkTransfers = ensureCorrectTransfers(refTransferIndex, lastClToElTransferIndex, true)
785+ if ((checkTransfers == checkTransfers))
786+ then {
787+ let newChainId = (valueOrElse(getInteger(lastChainIdKey), 0) + 1)
788+ let newChainHeight = (refChainHeight + 1)
789+ let thisEpochMeta = match epochMeta(height) {
790+ case _: Unit =>
791+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(epochRef)) + SEP) + blockHashHex))
792+ case other =>
793+ throw("Epoch already started")
794+ }
795+[thisEpochMeta, mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, newChainId, elToClTransfersRootHashHex, lastClToElTransferIndex), StringEntry(chainFirstBlockIdKey(newChainId), blockHashHex), mkChainMetaEntry(newChainId, newChainHeight, blockHashHex), IntegerEntry(minerChainIdKey(i.originCaller), newChainId), IntegerEntry(chainLastHeightKey(newChainId, i.originCaller), newChainHeight), IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), newChainHeight), StringEntry(supportersKey(newChainId), toString(i.originCaller)), IntegerEntry(lastChainIdKey, newChainId)]
796+ }
797+ else throw("Strict value is not equal to itself.")
737798 }
738799 else throw("Strict value is not equal to itself.")
739800 }
740801 else throw("Strict value is not equal to itself.")
741802 }
742803 else throw("Strict value is not equal to itself.")
743804 }
744805 else throw("Strict value is not equal to itself.")
745806 }
746807 else throw("Strict value is not equal to itself.")
747808 }
748809
749810
750811
751812 @Callable(i)
752-func extendAltChain (chainId,blockHashHex,referenceHex,epoch) = {
753- let checkVersion = requireElToClTransfersDisabled()
754- if ((checkVersion == checkVersion))
813+func extendAltChain_v2 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
814+ let checkClToEl = requireClToElTransfersDisabled()
815+ if ((checkClToEl == checkClToEl))
755816 then {
756817 let checkBlockHash = validateBlockHash(blockHashHex)
757818 if ((checkBlockHash == checkBlockHash))
758819 then {
759820 let checkEpoch = ensureCorrectEpoch(epoch)
760821 if ((checkEpoch == checkEpoch))
761822 then {
762823 let checkGenerator = ensureMiningEpoch(i.originCaller)
763824 if ((checkGenerator == checkGenerator))
764825 then {
765826 let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
766827 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
767828 if ((checkChain == checkChain))
768829 then {
769- let $t02395524009 = chainMeta(chainId)
770- let chainHeight = $t02395524009._1
771- let chainLastBlock = $t02395524009._2
830+ let $t02613726191 = chainMeta(chainId)
831+ let chainHeight = $t02613726191._1
832+ let chainLastBlock = $t02613726191._2
772833 let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
773834 if ((checkReference == checkReference))
774835 then {
775836 let newChainHeight = (chainHeight + 1)
776837 let prevEpoch = blockMeta(referenceHex)._2
777838 let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
778839 then {
779840 let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
780841 let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
781842 ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
782843 }
783844 else nil
784845 let thisEpochMeta = match epochMeta(height) {
785846 case _: Unit =>
786847 StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
787848 case other =>
788849 throw("Epoch already started")
789850 }
790851 let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
791852 then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
792853 else false)
793854 then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
794855 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)
856+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex, -1), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
797857 }
798858 else throw("Strict value is not equal to itself.")
799859 }
800860 else throw("Strict value is not equal to itself.")
801861 }
802862 else throw("Strict value is not equal to itself.")
803863 }
804864 else throw("Strict value is not equal to itself.")
805865 }
806866 else throw("Strict value is not equal to itself.")
807867 }
808868 else throw("Strict value is not equal to itself.")
809869 }
810870
811871
812872
813873 @Callable(i)
814-func extendAltChain_v2 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex) = {
815- let checkVersion = requireElToClTransfersEnabled()
816- if ((checkVersion == checkVersion))
874+func extendAltChain_v3 (chainId,blockHashHex,referenceHex,epoch,elToClTransfersRootHashHex,lastClToElTransferIndex) = {
875+ let checkElToCl = requireClToElTransfersEnabled()
876+ if ((checkElToCl == checkElToCl))
817877 then {
818878 let checkBlockHash = validateBlockHash(blockHashHex)
819879 if ((checkBlockHash == checkBlockHash))
820880 then {
821881 let checkEpoch = ensureCorrectEpoch(epoch)
822882 if ((checkEpoch == checkEpoch))
823883 then {
824884 let checkGenerator = ensureMiningEpoch(i.originCaller)
825885 if ((checkGenerator == checkGenerator))
826886 then {
827887 let chainFirstBlockMeta = blockMeta(getStringValue(chainFirstBlockIdKey(chainId)))
828888 let checkChain = ensureExpectedOrInactiveChain(i.originCaller, chainId, toBase16String(chainFirstBlockMeta._3))
829889 if ((checkChain == checkChain))
830890 then {
831- let $t02661226666 = chainMeta(chainId)
832- let chainHeight = $t02661226666._1
833- let chainLastBlock = $t02661226666._2
891+ let $t02873528789 = chainMeta(chainId)
892+ let chainHeight = $t02873528789._1
893+ let chainLastBlock = $t02873528789._2
834894 let checkReference = isReferenceCorrect(referenceHex, chainLastBlock)
835895 if ((checkReference == checkReference))
836896 then {
837- let newChainHeight = (chainHeight + 1)
838- let prevEpoch = blockMeta(referenceHex)._2
839- let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
897+ let checkTransfers = ensureCorrectTransfers(blockMeta(referenceHex)._7, lastClToElTransferIndex, true)
898+ if ((checkTransfers == checkTransfers))
840899 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)
900+ let newChainHeight = (chainHeight + 1)
901+ let prevEpoch = blockMeta(referenceHex)._2
902+ let updateMainChainData = if ((supportingBalance(chainId) > (computedTotalBalance / 2)))
903+ then {
904+ let lastChainId = valueOrElse(getInteger(lastChainIdKey), 0)
905+ let updateFinalizedBlock = getUpdateFinalizedBlockAction(i.originCaller, blockHashHex, prevEpoch)
906+ ([IntegerEntry(chainForkedHeightKey(mainChainId), chainFirstBlockMeta._1), IntegerEntry(mainChainIdKey, chainId), IntegerEntry(firstValidAltChainIdKey, (lastChainId + 1))] ++ updateFinalizedBlock)
907+ }
908+ else nil
909+ let thisEpochMeta = match epochMeta(height) {
910+ case _: Unit =>
911+ StringEntry(epochMetaKey(height), ((((toString(i.originCaller) + SEP) + toString(prevEpoch)) + SEP) + blockHashHex))
912+ case other =>
913+ throw("Epoch already started")
844914 }
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)
915+ if ((thisEpochMeta == thisEpochMeta))
916+ then {
917+ let updateMainChainLastMinedBlock = if (if ((updateMainChainData == nil))
918+ then (valueOrElse(minerChainId(i.originCaller), 0) != chainId)
919+ else false)
920+ then [IntegerEntry(chainLastHeightKey(mainChainId, i.originCaller), chainFirstBlockMeta._1)]
921+ else nil
922+ ((([mkBlockMetaEntry(blockHashHex, newChainHeight, referenceHex, i.originCaller, chainId, elToClTransfersRootHashHex, lastClToElTransferIndex), mkChainMetaEntry(chainId, newChainHeight, blockHashHex), thisEpochMeta, IntegerEntry(minerChainIdKey(i.originCaller), chainId), IntegerEntry(chainLastHeightKey(chainId, i.originCaller), newChainHeight)] ++ updateMainChainData) ++ addSupporter(chainId, i.originCaller)) ++ updateMainChainLastMinedBlock)
923+ }
924+ else throw("Strict value is not equal to itself.")
925+ }
926+ else throw("Strict value is not equal to itself.")
858927 }
859928 else throw("Strict value is not equal to itself.")
860929 }
861930 else throw("Strict value is not equal to itself.")
862931 }
863932 else throw("Strict value is not equal to itself.")
864933 }
865934 else throw("Strict value is not equal to itself.")
866935 }
867936 else throw("Strict value is not equal to itself.")
868937 }
869938 else throw("Strict value is not equal to itself.")
870939 }
871940
872941
873942
874943 @Callable(i)
875944 func join (rewardAddress) = {
876- func checkRewardAddress (address) = match getBinary(minerPkKey(address)) {
945+ func ensureNotOverrideOtherMinerPk (elAddressHex) = match getBinary(minerPkKey(elAddressHex)) {
877946 case pk: ByteVector =>
878947 if ((pk == i.originCallerPublicKey))
879948 then unit
880- else throw(((("L2 miner address " + address) + " is already linked with ") + toBase58String(pk)))
949+ else throw(((("EL miner address " + elAddressHex) + " is already linked with ") + toBase58String(pk)))
881950 case _ =>
882951 unit
883952 }
884953
885954 if (!(isContractSetup()))
886955 then throw("The contract has not yet set up")
887956 else if ((MIN_BALANCE > wavesBalance(i.originCaller).generating))
888957 then throw(((("Insufficient generating balance: " + toString(wavesBalance(i.originCaller).generating)) + ". Required: ") + toString(MIN_BALANCE)))
889958 else if ((size(rewardAddress) != 20))
890959 then throw("rewardAddress should be an L2 address")
891960 else if ((size(allMiners) >= 50))
892961 then throw("too many miners")
893962 else {
894963 func checkExistence (exists,miner) = if (exists)
895964 then true
896965 else (miner == toString(i.originCaller))
897966
898967 let alreadyExists = {
899968 let $l = allMiners
900969 let $s = size($l)
901970 let $acc0 = false
902971 func $f0_1 ($a,$i) = if (($i >= $s))
903972 then $a
904973 else checkExistence($a, $l[$i])
905974
906975 func $f0_2 ($a,$i) = if (($i >= $s))
907976 then $a
908977 else throw("List size exceeds 50")
909978
910979 $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)
911980 }
912981 if (alreadyExists)
913982 then nil
914983 else {
915984 let newMiner = toString(i.originCaller)
916985 let rewardAddressHex = toBase16String(rewardAddress)
917- let check = checkRewardAddress(rewardAddressHex)
986+ let check = ensureNotOverrideOtherMinerPk(rewardAddressHex)
918987 if ((check == check))
919988 then {
920989 let newMiners = if ((size(allMiners) == 0))
921990 then newMiner
922991 else ((allMinersStr + SEP) + newMiner)
923992 let deleteOldRewardAddressPk = match getString(minerRewardAddressKey(newMiner)) {
924993 case oldAddress: String =>
925994 if ((oldAddress == toBase16String(rewardAddress)))
926995 then nil
927996 else [DeleteEntry(minerPkKey(oldAddress))]
928997 case _ =>
929998 nil
930999 }
9311000 ([StringEntry(allMinersKey, newMiners), StringEntry(minerRewardAddressKey(newMiner), ("0x" + rewardAddressHex)), BinaryEntry(minerPkKey(rewardAddressHex), i.originCallerPublicKey)] ++ deleteOldRewardAddressPk)
9321001 }
9331002 else throw("Strict value is not equal to itself.")
9341003 }
9351004 }
9361005 }
9371006
9381007
9391008
9401009 @Callable(i)
9411010 func leave () = {
9421011 let leavingMiner = toString(i.originCaller)
9431012 func skipLeavingMiner (acc,miner) = if ((miner == leavingMiner))
9441013 then acc
9451014 else (acc :+ miner)
9461015
9471016 let remainingMiners = {
9481017 let $l = allMiners
9491018 let $s = size($l)
9501019 let $acc0 = nil
9511020 func $f0_1 ($a,$i) = if (($i >= $s))
9521021 then $a
9531022 else skipLeavingMiner($a, $l[$i])
9541023
9551024 func $f0_2 ($a,$i) = if (($i >= $s))
9561025 then $a
9571026 else throw("List size exceeds 50")
9581027
9591028 $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)
9601029 }
9611030 let rewardAddrKey = minerRewardAddressKey(leavingMiner)
9621031 let prevRewardAddress = valueOrErrorMessage(getString(this, rewardAddrKey), "miner has never joined")
9631032 if ((thisEpochMiner == i.originCaller))
9641033 then throw("designated miner can't leave")
965- else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP)), DeleteEntry(rewardAddrKey), DeleteEntry(minerPkKey(prevRewardAddress))]
1034+ else [StringEntry(allMinersKey, makeString_2C(remainingMiners, SEP))]
1035+ }
1036+
1037+
1038+
1039+@Callable(i)
1040+func transfer (destElAddressHex) = {
1041+ let checkClToEl = requireClToElTransfersEnabled()
1042+ if ((checkClToEl == checkClToEl))
1043+ then {
1044+ let checkPayment = if ((size(i.payments) == 1))
1045+ then true
1046+ else throw(("Expected one payment as a transfer amount, got " + toString(size(i.payments))))
1047+ if ((checkPayment == checkPayment))
1048+ then {
1049+ let tokenIdStr = getStringValue(tokenIdKey)
1050+ let tokenId = fromBase58String(tokenIdStr)
1051+ let t = i.payments[0]
1052+ let checkAssetId = match t.assetId {
1053+ case assetId: ByteVector =>
1054+ if ((assetId == tokenId))
1055+ then true
1056+ else throw(((("Expected " + tokenIdStr) + " in the payment, got ") + toBase58String(assetId)))
1057+ case _ =>
1058+ throw((("Expected " + tokenIdStr) + " in the payment, got Waves"))
1059+ }
1060+ if ((checkAssetId == checkAssetId))
1061+ then {
1062+ let lastIndex = blockMeta(mainChainLastBlock)._7
1063+ let queueSize = ((nativeTransfersCount - lastIndex) + 1)
1064+ let checkQueueLimit = if ((160 > queueSize))
1065+ then amountGtEq(t, 1000000, queueSize)
1066+ else if ((1600 > queueSize))
1067+ then amountGtEq(t, 10000000, queueSize)
1068+ else if ((3200 > queueSize))
1069+ then amountGtEq(t, 100000000, queueSize)
1070+ else if ((6400 > queueSize))
1071+ then amountGtEq(t, 1000000000, queueSize)
1072+ else throw((("Transfers denied for queue size of " + toString(queueSize)) + ". Wait until current transfers processed"))
1073+ if ((checkQueueLimit == checkQueueLimit))
1074+ then [IntegerEntry(nativeTransfersCountKey, (nativeTransfersCount + 1)), mkNativeTransferEntry(nativeTransfersCount, destElAddressHex, t.amount), Burn(tokenId, t.amount)]
1075+ else throw("Strict value is not equal to itself.")
1076+ }
1077+ else throw("Strict value is not equal to itself.")
1078+ }
1079+ else throw("Strict value is not equal to itself.")
1080+ }
1081+ else throw("Strict value is not equal to itself.")
9661082 }
9671083
9681084
9691085
9701086 @Callable(i)
9711087 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"))
1088+ let withdrawBlockMeta = blockMeta(blockHashHex)
1089+ let withdrawBlockHeight = withdrawBlockMeta._1
1090+ let finalizedBlockHeight = blockMeta(getStringValue(finalizedBlockKey))._1
1091+ let mainChainLastBlockHeight = blockMeta(mainChainLastBlock)._1
1092+ if ((withdrawBlockHeight > finalizedBlockHeight))
1093+ then throw(((("EL block #" + toString(withdrawBlockHeight)) + " is not finalized. The current finalized is #") + toString(finalizedBlockHeight)))
1094+ else {
1095+ let withdrawBlockChainId = withdrawBlockMeta._5
1096+ let isMainChain = (withdrawBlockChainId == mainChainId)
1097+ let relatesToMainChain = match getInteger(chainForkedHeightKey(withdrawBlockChainId)) {
1098+ case forkedHeight: Int =>
1099+ (forkedHeight > withdrawBlockHeight)
1100+ case _ =>
1101+ throw((((blockHashHex + " is on an alternative chain #") + toString(withdrawBlockChainId)) + " that was not approved by majority. Wait for some blocks"))
1102+ }
1103+ if (if (isMainChain)
1104+ then true
1105+ else relatesToMainChain)
1106+ then {
1107+ let recipient = i.originCaller
1108+ let recipientPkHash = take(drop(recipient.bytes, 2), PUBLIC_KEY_HASH_SIZE)
1109+ let zeroAmountBytes = base58'11111111111111111111111111111111111111111111'
1110+ let amountBytes = toBytes(amount)
1111+ let elEventData = ((recipientPkHash + take(zeroAmountBytes, (size(zeroAmountBytes) - size(amountBytes)))) + amountBytes)
1112+ let elEventDataDigest = blake2b256_16Kb(elEventData)
1113+ let calculatedRootHash = createMerkleRoot(merkleProof, elEventDataDigest, transferIndexInBlock)
1114+ let expectedRootHash = withdrawBlockMeta._6
1115+ if ((calculatedRootHash == expectedRootHash))
1116+ then {
1117+ let tokenId = fromBase58String(getStringValue(tokenIdKey))
1118+ let transfersKey = blockElToClTransfersKey(blockHashHex)
1119+[Reissue(tokenId, amount, true), ScriptTransfer(recipient, amount, tokenId), StringEntry(transfersKey, setOrFail(valueOrElse(getString(transfersKey), ""), transferIndexInBlock))]
1120+ }
1121+ else throw((((((("Expected root hash: " + toBase16String(expectedRootHash)) + ", got: ") + toBase16String(calculatedRootHash)) + ". Event data digest: ") + toBase64String(elEventDataDigest)) + ". Check your withdraw arguments"))
9891122 }
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- }
1123+ else throw((("Expected " + blockHashHex) + " to be either on the main chain or relate to it"))
10121124 }
1013- else throw("Strict value is not equal to itself.")
10141125 }
10151126
10161127
10171128
10181129 @Callable(i)
10191130 func setup (genesisBlockHashHex,minerRewardInGwei,stakingContractAddressB58,elBridgeAddressHex) = if (isContractSetup())
10201131 then throw("The contract has been already set up")
10211132 else if ((0 > minerRewardInGwei))
10221133 then throw("The miner reward must be nonnegative")
10231134 else {
10241135 let genesisBlockHash = fromBase16String(genesisBlockHashHex)
10251136 let emptyPk = base58'11111111111111111111111111111111'
10261137 let genesisMinerAddress = addressFromPublicKey(emptyPk)
10271138 let genesisEthRewardAddress = base58'11111111111111111111'
10281139 let genesisBlockReferenceHash = "0000000000000000000000000000000000000000000000000000000000000000"
10291140 let issue = Issue("UNIT0", "Native token", 0, 8, true)
10301141 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))]
1142+ let genesisBlockMeta = ((((((toBytes(0) + toBytes(height)) + fromBase16String(genesisBlockReferenceHash)) + genesisMinerAddress.bytes) + toBytes(0)) + base58'') + toBytes(-1))
1143+[BinaryEntry((blockMetaK + genesisBlockHashHex), genesisBlockMeta), StringEntry(chainFirstBlockIdKey(0), genesisBlockHashHex), mkChainMetaEntry(0, 0, genesisBlockHashHex), IntegerEntry(minerRewardKey, minerRewardInGwei), StringEntry(stakingContractAddressKey, stakingContractAddressB58), StringEntry(epochMetaKey(height), ((toString(genesisMinerAddress) + ",0,") + genesisBlockHashHex)), StringEntry(finalizedBlockKey, genesisBlockHashHex), issue, StringEntry(tokenIdKey, toBase58String(tokenId)), StringEntry(elBridgeAddressKey, ("0x" + elBridgeAddressHex)), IntegerEntry(clToElTransfersEpochKey, 0)]
10321144 }
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")
1039- else {
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))]
1043- }
10441145
10451146

github/deemru/w8io/026f985 
145.24 ms