diff --git a/artifacts/demo_chain_specs/polkadot.json b/artifacts/demo_chain_specs/polkadot.json new file mode 100644 index 0000000000..2d4525f8ba --- /dev/null +++ b/artifacts/demo_chain_specs/polkadot.json @@ -0,0 +1,47 @@ +{ + "name": "Polkadot", + "id": "polkadot", + "chainType": "Live", + "bootNodes": [ + "/dns/polkadot-connect-0.parity.io/tcp/443/wss/p2p/12D3KooWEPmjoRpDSUuiTjvyNDd8fejZ9eNWH5bE965nyBMDrB4o", + "/dns/polkadot-connect-1.parity.io/tcp/443/wss/p2p/12D3KooWLvcA24g6sT9YTaQyinwowMbLF5z7iMLoxZpEiV9pSmNf", + "/dns/polkadot-connect-2.parity.io/tcp/443/wss/p2p/12D3KooWDhp18HYzJuVX2jLhtjQgAhT1XWGqah42StoUJpkLvh2o", + "/dns/polkadot-connect-3.parity.io/tcp/443/wss/p2p/12D3KooWEsPEadSjLAPyxckqVJkp54aVdPuX3DD6a1FTL2y5cB9x", + "/dns/polkadot-connect-4.parity.io/tcp/443/wss/p2p/12D3KooWFfG1SQvcPoUK2N41cx7r52KYXKpRtZxfLZk8xtVzpp4d", + "/dns/polkadot-connect-5.parity.io/tcp/443/wss/p2p/12D3KooWDmQPkBvQGg9wjBdFThtWj3QCDVQyHJ1apfWrHvjwbYS8", + "/dns/polkadot-connect-6.parity.io/tcp/443/wss/p2p/12D3KooWBKtPpCnVTTzD7fPpCdFsrsYZ5K8fwmsLabb1JBuCycYs", + "/dns/polkadot-connect-7.parity.io/tcp/443/wss/p2p/12D3KooWP3BsFY6UaiLjEJ3YbDp6q6SMQgAHB15qKj41DUZQLMqD", + "/dns/p2p.0.polkadot.network/tcp/30333/p2p/12D3KooWHsvEicXjWWraktbZ4MQBizuyADQtuEGr3NbDvtm5rFA5", + "/dns/p2p.1.polkadot.network/tcp/30333/p2p/12D3KooWQz2q2UWVCiy9cFX1hHYEmhSKQB2hjEZCccScHLGUPjcc", + "/dns/p2p.2.polkadot.network/tcp/30333/p2p/12D3KooWNHxjYbDLLbDNZ2tq1kXgif5MSiLTUWJKcDdedKu4KaG8", + "/dns/p2p.3.polkadot.network/tcp/30333/p2p/12D3KooWGJQysxrQcSvUWWNw88RkqYvJhH3ZcDpWJ8zrXKhLP5Vr", + "/dns/p2p.4.polkadot.network/tcp/30333/p2p/12D3KooWKer8bYqpYjwurVABu13mkELpX2X7mSpEicpjShLeg7D6", + "/dns/p2p.5.polkadot.network/tcp/30333/p2p/12D3KooWSRjL9LcEQd5u2fQTbyLxTEHq1tUFgQ6amXSp8Eu7TfKP", + "/dns/cc1-0.parity.tech/tcp/30333/p2p/12D3KooWSz8r2WyCdsfWHgPyvD8GKQdJ1UAiRmrcrs8sQB3fe2KU", + "/dns/cc1-1.parity.tech/tcp/30333/p2p/12D3KooWFN2mhgpkJsDBuNuE5427AcDrsib8EoqGMZmkxWwx3Md4" + ], + "telemetryEndpoints": [ + [ + "wss://telemetry.polkadot.io/submit/", + 0 + ] + ], + "properties": { + "ss58Format": 0, + "tokenDecimals": 10, + "tokenSymbol": "DOT" + }, + "forkBlocks": null, + "badBlocks": null, + "consensusEngine": null, + "genesis": { + "stateRootHash": "0x29d0d972cd27cbc511e9589fcb7a4506d5eb6a9e8df205f00472e5ab354a4e17" + }, + "lightSyncState": { + "babeEpochChanges": "0x048edc0df46d8dd7b4d2976d124920bf94ab2bdd9058f837f3a502586a70d22ddbd24ddc0001733eaa1000000000d347aa1000000000049a41a36f474af1af3046324e211e0edba2f8cc50390dff82976981bbd67245db2957dc0001d347aa10000000003351aa10000000000486ce7842747897a71c3dd8462432fe113713580f11146d55ee881318f910e3797f60dc00013351aa1000000000935aaa100000000000000c86ce7842747897a71c3dd8462432fe113713580f11146d55ee881318f910e3797f60dc00019f170000000000003351aa10000000006009000000000000a50466f60202b962c40e58fcf3481f5773dc178b9fe096f81511eaa4c7bad20e612001000000000000009c40155989f6072e82caba245d7db7e40a60f866b403257976b89aba6be2b55b0100000000000000ee3b07c54f0d93945caa98d8deea125865e36dee14644453fb07176d4605bb2c010000000000000072ab87b654d80294c876cbefb534b3344c2f64159b015b89221331ec2145417501000000000000008e43fb54c6d8074ba65ddc6c1b9c54a9c9f0508ec939d5b1746ad2bc42069c600100000000000000e2782e5b1d9962dcb6c006b797af79017be14346a6c2086ff132776ee7e74f53010000000000000020352ba0565811731625a8001d26f5d899e5856dedd0f9c6bc3bec2995704e5b01000000000000004c9886e2e62ee92a6778d6a7928052732044b64fa61969cd8e37f3f7e3406f72010000000000000012f7e35aedc710f8335cc813db106f2a569c6224505416e33c241e625993a86a0100000000000000dceaa05fb95e70e99b9fcfa547a67d067b1ec24b1e795bcd739ff3fdf1c2c9160100000000000000002e496e564f088a075525d2f9155aadd1a7eb017fa36f9e16096e9db7e1693301000000000000006a49a129620f4318c4a99b69c28cbe5f94c7578bbce50bf2627c61590f68df750100000000000000f6dddaaaa53b57763610037753656b591d90fa81efbadcabbeddf7378c23602701000000000000009601c5f103f77e1cb78d4e03f2585320142cbb4fd6c5c37f21edbbb2d343eb560100000000000000466c0e97d043a4b0f4c3ac4849e11f901e9b31b28f8b3e40b7cdb0ba7f77480801000000000000002049288b4dbfb741109778c602f9308daf2e31b3b66e9aa550065e73c6787d7c0100000000000000e67c524e443cda4cd27dfcce70488a5d23a93c8c46a5e83ef5a69eff3a02fa5a0100000000000000ca4fb6a27ee4ba734e8e8caac9ed440170a99efe98af430a14a3eaa4b0d03d600100000000000000400c83c89f541c02338cf113c5a841d810bf3bf17c5c6e78efbd637059005f7001000000000000002e85d3d2c07aaf1c0a5f63f544c34b87cfa90a98c4f6167e86cee0b74a20cb1201000000000000007c5f58a83f8101943c089dba3ab906c07811e853444aa58dbcc986c4095fbe7c01000000000000005494142902284943201b7cf610306e8665eeeec87c014d607175c3f50f76103b01000000000000001822493200c35242a149070784dca5e7012a8a52b61cd218ec7d65e469e8cc560100000000000000dcf6d4dda860d902eb4acb8adff1116c637c12eb9d0633caa8fd0b65a30c8105010000000000000042e377034ce6b2a582bfd66c465252ab10ce790e4f0d3bbe99a42ff86b29965c010000000000000052e281ebf2cb6e1751a844d92574869e5a06e596bc41404de1fe55e99980dc6901000000000000004e2753547f6ec0a896bcbc55b9eeab875e8019acdeb10b979210af63f24c4b740100000000000000822467882ab8bd2cd75152843a948b3e56ae1da6aac9b66ac4cba1448217d8410100000000000000f63e0c859002c868d1e8bf7b36558b7b3f4a033f13850862ad643bc99628f335010000000000000090fd0815e122cc480aaa256b319405ab08f867d414dd59736bc81b7f054c59700100000000000000046c86bcf2260b9e862c5867def0e1a528c32e64ce0cb20d41bba00f30013a690100000000000000d416213c0b30df8f5aadf00642a4777dcea76b12836c51a98abcd133c78899470100000000000000ae831c0a4d22eeff12f679540c229029e321499477451768b8999b1191d6164801000000000000006ec27dfa7ac9d35eb002c55d3e4d56b4df928dd5c44323ac228305741c9e09360100000000000000b89cbc83a386d6f5d4fed93289ee50fdf69d77369ca0c9a8b962554e3fc0d37e0100000000000000e61da4eefdd14434952c58dd1943f7f63185d03321ccc8835e4216badd16fc19010000000000000078f66da37371586d480a8c4dcb2fc772c7c3c185961b5757169cb3b72c12436b0100000000000000a20797f3a8669a909adb22a3aee2844dba82d231cc33f5d9be0e2c533cb82a670100000000000000e297620b731b4958e3c6aa06611c6aa5a45f7e116362d64954a0a330d2a98f33010000000000000088c2166cef8e248c6dc7f801967f6c936b21ecff6f061035d9f95cbaabbcbb0f01000000000000005a7a6d3951924738f27fec8c0baa71a0f518a2d56d8289a1887d3d6805088c220100000000000000049e89e200ca2e92ee67afb644b216f3e99c8b4eaf26c1f0e42038850d0c617901000000000000004077191c8d78ed00c81b74788215db40d498f37252f9966f57e96c9d3f6af31701000000000000000ef6f09a9e310abb5c57dd7050a94d56d766772b80789b997cbb40f3b40f625d0100000000000000b25892ec76bcc88536409e440cb14f9de9589c4efe2b69608fff594885a2fe6501000000000000007cc03ffbfb187c1ea32cf4d25893238aae9073b2016084052a6defac64a7e36c01000000000000003af71b42b712323aa28fd7a2099c4f8b8071e3ed27c8a52ff2cdff5d1a5eb66b0100000000000000a88864a0dc9e292aa7cc8eddaa8dd8b6be2a4bc7e8f290023c6604e5c4ad1a7a0100000000000000dc68569b46a09aebabe8fc4452e293fac635e4a2889739809b32e4e2303e3f71010000000000000034ffee048e511f4187a6f40339650ec60a3d99ac5a1158ae162c5729b59d51740100000000000000be7c58318c49ff328d53a6d67830a8a046a41f5124824d3ce2e72cc9965ef57e0100000000000000a693f218033b3eb885bd2c7793227834d1ff3350c296e49aef3d8d801d5719750100000000000000b06e3ee1ea6420fb73ebd502988420f51b977a83074e1aa5daf0121f4a8b6b1e01000000000000003843abe933fa3ce63f3a5e422e13ec05dc9c0e8f150b93a0fa97f1b193cfba2d01000000000000009cdd57a06bd22d104d539527a19033620becff73dd267f0c2f9f13bc37b0d32c0100000000000000e020b5e946e4c6b0603ceac71b44c330fa7d9cb3e79791ebe1e16bedbb9c71000100000000000000a86c7bdf11794e554439b09f9f294c8e0abaebf447c7bc54419434b8b95f864901000000000000009e9f565a8cb6e8f2154a9833735930a04003505856c3743a0f71afe64c7acf71010000000000000042e4c41a899dfb238649e5b17dc232c2699353635d60e6a3bdcd71f9b82cda300100000000000000a24cc4a40afe5d37968f8d6c7904181a1390d5e718ad04a27ace2ea62f52376001000000000000002261bba26f785cfff606f086f5db420a43a4322fb9d225410a140acbe3d3a405010000000000000050a257ba8dddbf08556f5708bccb587ff4dfbfad15f217d422d7bcf2a7f7f5600100000000000000f23d1b22d1b03c9fb6eb203c85761fe429a60c38d6591d215e873d62f5d2e4010100000000000000283a77cab50b96f99a8e8287c1488ebbcf31fc3daa953ffa99ac16db982f1e12010000000000000094e80daa135f9283d6e8c00c00840ef766863b7d89f354c208b75062f9507c760100000000000000ee579514d7f544fc9fb8d6383ed7d109ee98a411bb4b0b45b9354b0f73fed9720100000000000000b8e999c053a20108e3380d6cb1c2dd2b8e6973c7b2a1f354ca91068c1c1eb83d0100000000000000e8308668e9f16683cc739791a6dd530b819f45e4ade2113ee2f27eed1c51d1200100000000000000b0b313e6391bd3cad2a2c91e4fdaff1404e8a5e2014e4ddbe89f0b7a63e28079010000000000000074b89b94bfe9d61d16ace3eacec820305edfa6a7286ada941e92cfb0bd8374100100000000000000b25eaa07b529a889d38e0346761842f8ca2e970b31038d174c88c7fb667718270100000000000000825e4307d8b2b4387bdadc97f6aa854152dcb5ea892bd1e6790afb1dd83e2e2d0100000000000000a889c98c4c129efe5ecf6e78992d19903205818ca2b760ec25a0b7debb7a2f18010000000000000026d421de2e7251020ac2f8b8c7e348aa904dcaf0b6d5d73fa0113b476f7dd903010000000000000020d5041fd7749a76b9862d74f365692ed6186dd95b0436df82089918920bc3580100000000000000bc56c07cea21bcbbe058aedd2ced9fb4757caead55f96bda9bed1c9669c32b640100000000000000ee1c578a2f792ff3237d645124391b6422b16724b1da5f1b4296f422834bf01c0100000000000000da5c9a8e3df09d9e2a73aa5453b53998b426fd747e887faeb9b2dc99a03cd12201000000000000006ccf2ce8e149999a7bb996faa65194e60aeb7bcd1937c787f886fe979fb49e66010000000000000082b820c5bee8ee77e35203dab387f3434b8502e5f1c35dfb2ad15b5c89d47b3c01000000000000003ef7b532bad1e78d67254bb738d2e5aa357aa04dece89ca3aeadcc8b77efe14b0100000000000000b6ea2250aca814c227ff53de081c337cfdbdef2eb3b0416555589fdc15cf64360100000000000000422318d2ed50f9e42bc2451394ea2faa9b6e0a2454d1471a8ad6ed7b2164b81b0100000000000000b4b145ce385b4a3d83f2daac46a61874f80e58c468dd624acc09a558be02c27d0100000000000000ccebbca14a079b3f6a61898b07592456869c753f951401dd3696788419b5952b0100000000000000d04077347325618eb5cef03729a157b910fac54ec7e344e65b6945fb9fbbeb3b0100000000000000069fc7b8027f7088057362a588ed9af23342e37b70fa163cb47897f7960025580100000000000000fe3b55d17e25c44a3568885d9d37276df81fa5225d9d73ee67321c7826581b5a0100000000000000dee6847832968c1e240c64eb4d2cfd8f5ff3be16d63301638049c8cc7db83059010000000000000040a2527ffa7d30d788eca127d435c8b5aa48972cda538b9a1627a57e85c8fa190100000000000000cebf2df4a8cae34e2f4c645863327db8a10b19119ab7d1cd887a4cb8acc0481101000000000000008ee9a6372d159dd413e241b3201ae4cb2ae8d05fe95fbe1e565d81000dc418750100000000000000261ac3229b4bb7a376c37f17e287b2eb596d3b478370b722b6b41443d870813201000000000000001a36d936f4692ac8387ac0ca1f051970ae480271e39fc134436b86b8ec83b25d01000000000000007886559a7121bd7f28b06ce499e0bc3de3d0adf1abc47c6e0461383c7098237f0100000000000000e03dd3bbb140ffa44e0cc0e1846967b03aecccac78f6e2e0a1fd3ac0d34f554a0100000000000000a8818217d40fd73cfb5c28b2402a2c6049fd17f99226f3331b6bf328688e3c4401000000000000007affcc9e0c86c66957afb75d760842bfd374949da725718c0bd3edbf6a1bd7310100000000000000eabcf59549db01c112376fd042e3ecf95b1b3b5ae8e0e744965cad5880bf9e0e010000000000000068d6533bda9e474fabac2aff0e1e6aa7ac48509802f7cd29b5a4badaba2bf37f0100000000000000fa76b5548c290e38efd3aeb5bb478de80b0e4d10b09b758e0b0f0971993e6b1c010000000000000004ba7eb24012b133b20a8021b603a1483c4a5b9ad3415a4d7ca2b1ad625719550100000000000000202e3405e49bb882f1d49efc4a4adc5b62dcc96ec18346a48aad5a510c189b500100000000000000dc02c19ac49087a2a0c5188af826e5ed6450f5041f00ee8e77bc01b12945ac0d01000000000000001ca57b22ae230979adc98a3aa05d47f1196c27eda66bb6125a868583fba6e5420100000000000000ea6acde5149e930af7bc3b17b7f0bdcf12dfd3dc3437f774f823bbeef420a97201000000000000002ea86a65c1e3749548d3c56eb537d21e1756895e35ca99a9019b8606c47bd214010000000000000014e2f25dd3376eb7978d413c14322704a2ff3d9c0c2971acdcdf9720c2c13d6b010000000000000014cf97e739cfd033c2828f25ad3f15e8f6ef62ba97dd74164e77e61eb85454260100000000000000eef6e320387caad3fa7bf295c60b85adf0a6f5a19144a4433e1841b4a72e07410100000000000000a07f151db53097c2da9dac4b2e0f194931a677a3ba99df0f3976e34409fd64760100000000000000809a2c451363ab14bb2272aa972a2b1a1de3386fe2bd47113ba4819d67b6fd6501000000000000004cc9ff5edb36e361b088b0eff52fc6e6559c1169ff87ccdb62503bceab7c7445010000000000000040dab7f2e50b7ccee4e3a6223ac09882654079b695b110ad6401558959c2360d010000000000000004065673fbef2c9dbd1b79088e0e3cd6e39784ebb792ede843d9e7988da85c4c0100000000000000fcd5f4c4fe11f20ad99dc8345b7dc5600caba5d5b7d3f499c3253c095152d45401000000000000009254313d03095e6b374e43addebc950956bcb34f2d11a9c557514c9991b3aa0d01000000000000001e825121b8beecb30e9962a555ce06b9e2c65fcf3b0023178556330d565bcb4c0100000000000000e06ae0c49573816e158f02c5263a7b167c2ff7bc5528b13c1cc5a2ad0a34da16010000000000000038b723ee73f8083592437eb9f2e436ad7b694dbaa7599d154a9e3e01b14b69040100000000000000042ca33fbebb9f50bd3ee55c6eef27124379729ce2670914d1a762ebd5ced55c0100000000000000aa819492e4d782526781e8f9001f93d2b9a23142886757ac932702930b9a991e01000000000000008c14a0d64bbb88f3546c49bafb1f6bbe3d59cb277af2fc97f19aee0b80bdad0e01000000000000006834aee6fa1c48e229ad7431b77181ff03dedfa486aac6eb7880ec9950c445540100000000000000b48cf50a4f94e83450a791d6de965c3e8127c1c915208f2b85df4c3a84b2042f0100000000000000c60a9f5f89ea3a56499bcd39bac7e038c25f5b7720d873fdc12b68d2531eb650010000000000000040b77fd8fcabe868dc7f2a08bf14c67e4d433886c3cd3738d1b0b9c649bafc2301000000000000008c43dc50f9ed5bc7be6b4a648957ee5b01a2cbbf967077a6044d4b92f2c715070100000000000000fa81c1b7635c3f695915443a2dfc030e980cae09e592f555edb67436aa11215001000000000000001296762372530d2ccabddcbd204fa90217ce28c9365c5cf4a4eb9f46545b786a0100000000000000fe621d474a018c4e2265c864e994a129614dfb473339453f45a5510587d0174b0100000000000000f2b63387ce5b649f9388fd1be38ee4357b48dc0146e78b91f8f6469a78dc9f580100000000000000b2ba57f89fba50ab178f10f10f2ff79f6061cfec808679868eb7ddd8b08031340100000000000000e694e453023e9989a59e414a8783f9269e933574332c77067fa7ec2b9b6876100100000000000000dc702f22412e64b699d65c66ea2d0857e7b94c0448346f86068e658fc00c5a2c0100000000000000ccb4e6006ac696d5050bc790beff6eaf61a5dbee1a070f66c824b962fe177b6901000000000000009acfd215519f40156749868afc8d56e015759f71cf183fe68382e8c02c75b251010000000000000038f3f4c693034fb614c804ef2854850286df0b1411e5a0c83513ef4c4fa487050100000000000000de5f9f5ad3209502cf429630c2038b8818b6f8ce5685c2730077349802c579250100000000000000649d1a54b0a158350238c017a71aae21e3bb73497187a010d97e1e1b21e43b6401000000000000001cbfaf2b91ee79c6288ad01dd5787070b34d5e1b8253a1765904eaa7d0b93f02010000000000000036a547b4aca95274437f3876bec0447f775eacd01b09d95869390d326a596d450100000000000000a811667da1a12b408e2eddd3fe118403e1f8926b703104fe34193b4fca229d5701000000000000008e83fc9e157adcb687b4b994326f6de340d80075bdbb590eeaa3f29f457ef3560100000000000000b2afe6968bf90de3f8cea025a2b2b0b560b1899fd23343e52c778ab45e1f685f010000000000000026f2af62a2f0d847e3d2cccc93ec7f98c80a7b6d1bcca4cf1c4a6fc7f81775010100000000000000aafb720e50ac6fe69aa177dff62a733a0e98cc0fe7c35e591127479e7e94d5430100000000000000a8f7368dec8f4f30db015c4362e03cd588c6e60f2f4f69912ee4aafb35df38620100000000000000e6767e8c251c74826054421ff499297c13ab6a4e84ce10e0dfae4e21b64aca7301000000000000000481a58bfdafecabbc96bd170a0ec04cc35100f1f928cca3ecc63b3639e47679010000000000000056935ed80a27ac471336a7c5a8b0e73432ddabdf5fe8992390cbae33a020883601000000000000008ec5856a5fd17617c0af76efea16a87d0c5e769eaad39e91c40dac93fb067d5d0100000000000000b0d7d82ba2eca517d6d899525672a1d236f907565785e41ba80296aad19dc57f0100000000000000e4be18b8f5905bc41fe3cba2e5350d405e76036328042ae7edfbb6b6a9b43d5a010000000000000038a69f047c05d50988318a333c2a6bdde4b778592d66328bcf44f1472c1dab500100000000000000b28eace0661acec97215230b9aae3c2be19ef43e9eb90554ab44b51c6180362001000000000000004ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b1402010000000000000036b1aeb61d78c234c0448c0622c570c33ad8fa7b5d7d12102ab323b7985d31690100000000000000a6cfacf0aff2d5c6e8eadf71f397a64f2863e5f0b8793e3068aebd5b3030e13101000000000000007eb2b0b6adbe5a5bad38f46db207f94c896d419661f4ab8f21e302a543df9b1101000000000000004014ed541e698a7a87888c6b5f0c54d74de28c8cd3bd8f1b1f8fd7fdb757cf330100000000000000b032afc9e8d2abc223f23c1d1e1776b3c66a23f5917a7669d69c2eda81b08c3e010000000000000048ce0aba6f1554e139568b4d2358d6cca9bc291d3600787cc3e732291002ca22010000000000000092239fbae2557ff2ea3952c962e478e6ac2a5b3e3cfffb0eb40e8d41860ab0470100000000000000e82715ac0ec2e1f41af952f272f20ef2d2ef826c441c6f33a95522270e57db4b0100000000000000469d81e8b43725a64da6b1ce10eb53eebe1aaebb9703f75ed452e12f45d262730100000000000000285987285ceda1670b1a2fc5c5cf8578a368d63aabfdbbee83ea05db6ae376470100000000000000c4f22a0641190f1bceebea3f8280f22469d6ac0d9b27bcab27d778ac517d2479010000000000000026106dc6fa26823ed60e52e0b1a164dd897be2f617bbf24ddebd9ab34bf6de7701000000000000001c71bcb434190e911175317142b8589619ea3087fb2048a9117607b7b11d11300100000000000000a8527842f1040269688813eb1cf64f525cac5f9219feac35b2d46bcd2df52d100100000000000000a670be090a366ff66d8f7d1eabb7514252222507111e53430bd437a8dbe53a52010000000000000018261ac5151f160bc419a8e44d85fbd4cd8669decacb23c8d7f36f316cbb445e0100000000000000fc53d15453457faadc5540c5853f54324eec395d3647fbf99d5e6e97ef3876760100000000000000544d12f359dbe87200565a9697af85b936a1b5f9d0a363f2ee540ec544aa761e0100000000000000fca464b97dee2e318ad8d4516fd606a5401f5d15467110112a3326ef96ce00760100000000000000864cbd281011a154d93d0320865ad67ae442bf0985f0ec220e2c7db4b095993101000000000000004c696de688ef5d4d5899d1e596a81fde52db76757669bd0051a155fb2335ed0e0100000000000000382fb32d7c8868ce3765e9ccfb462c04071a3d70cab3382c796a9115ab0c310301000000000000008a6dbf87f769167b4eb982f63b946f96a1f223b6a6f2789183fec09581b8e9060100000000000000b027ae418b6c79d9f3a2b05df499d3aaecfb327e6b9d7995a022dc5265ed76180100000000000000eed7e8e8a64dfa89c548a31c1b9fec7af5aef4dbbdb26997b2ddca72d4f8790c0100000000000000a811cc491bb3487d5e604dcf6dca3bf529437162f3b8cfb8514ffab16809ff600100000000000000fe2848018ac215f72f551e58dd2d065d99b788b5a7aa59b9f9fe47a5bdbc046d0100000000000000b6ed5b0c17ca7560c71f1778694741009d3da979309617f0bb992084019e25290100000000000000f853a1534a3af56217661420536dd7bea0db6f6db843d8fead77c308ed7dcc7c010000000000000004b0ff0440c7e131b891a3c13c6f7f0233dbe80fe90dc097f8c5566f2bb49a5f01000000000000005af4895ad43e058a09b4982b8c78021f1ae6cdec9f6633089f32e948ef0d2a11010000000000000028702457fd7ea52bb88284bfcd721493ceae3ea984492a1b82c55efa1b62fa39010000000000000036550a8edfcf14f96e29a7901f5610b57722dbd68b48608572e98468c5bc1f6901000000000000008a51ec3cd1c7e1e5cdc0e3697dd028337ba54e18169cbb241140dbdcc928695c0100000000000000c80832d979a4ba72f7179c346fe660490c292689da81d790baa30a76b598ad5601000000000000006ef86d4533f47ffd133c63b9575c17234309ab6e16f487ae7cd8914169183c66010000000000000056606b6532cdbf27358fd067d61c2a65e4b3e8934c266a857320ff18e5c7654c01000000000000006e8ab85645445eed3828ed583d9a0af03a682fea56d16f833970a3289088e2510100000000000000d096cea7ac5f1bbcaad09ed4723a23fa3b582cc352182a49f8e4511acfa6f87a0100000000000000481ef876bba4865bb88d141606632b3a482c4e5c58c9c30786f6a279eea8a7780100000000000000f403ea18b9e4e9075319b30bf6b6201dd90d012fe4ba28a1c759d0822b9e550901000000000000000690823277fbe96c145c1686519038d301d63bad07d343810506e2cad4b1145701000000000000006c06a116c1a75e2e3b46a7924fe23ca8d58d2a32acac4ca8d0a1e23e3b4c4720010000000000000094d89cb8df2b03c76d41a6521e5803d6f98e204e1839b9ea747dc7e253d35b7f01000000000000009ce314a687a2e8754e1351cda727fdc20e473c08c8bcf5cb70c9a048b571540301000000000000002801cda4aec5f013c3eb504100b1e29e0e65423219d7c6b1b48b0a424a42307c0100000000000000ccb5a9652f3be5d85fcab3d0b8c2eae27519ae2f7befa40c34b89751bbcce40001000000000000005258f48e31bc89f5d53ea6a12eea9698f8e72c6068ac1588100d8632bc674d1e010000000000000094de02a2418c67e938e449c2297944e13cf638e67110299f14cafd5bf2fc60140100000000000000540926fefa2d0424fd451bfca39a01c0e1a3fc811406e127d1dbfdc6cf9e9770010000000000000038c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e85290100000000000000a0b7bf06b6c030493f2107c1f2c4154b98b677fcfd461e5817b909f31223a5630100000000000000eab9946bb96a047e9c2fb0e6db8236e46192bcced0c8ea7319142a73cfaf000401000000000000009a53749c83cc06460148d884f1ea5b71897466b237cf16baa45395d78ce48c1a0100000000000000f46eb7a2664580b8655261ad48df75d27404fa23ec47012148dca3c48783bc39010000000000000088fa8bb07ebce99964718c65d0d6f1b091ef2f4d4cdf7b94a22c42c007ecd70601000000000000008a0e2d0af87ffb812f6e6ec229d02056e812cc4f5f5743cc638a7d3f279f0153010000000000000092e5bb9d0906f768dbdde0696b78e493cc78dc1f68789575b24f0b962799b51e01000000000000001ab9d2c814ed7a719ef2aa94dcf4db8aaa0315a59d4b5699e86656a6ee9ac5610100000000000000b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d010000000000000010e37a12fc6ed768d1a2d33c8abc6db675381dfe69c832abb77d9ba2341b3c4a0100000000000000bc62cca37518b73aa22efed6a88147f84af5db7b82ef7671d9bbf03c76d22b4901000000000000000e21a03fbe9885a475c4875f3f912c8703945e99cd2a85f75258fda7b6022b7c0100000000000000206cc2601e4cc1c4d543c1f22eeabb29d72dba4e47630882b2c783e6d3d1935401000000000000002ef372f7d4c71a60f76f65c8ba860ccdf38a85db80963c7f569990ae3865cd470100000000000000068ea8205451f7fdfc6e72059bc58f56cfbd2edcf349f3514de9b00d0c54856801000000000000000e973b21dcbf05732a16fbb925cc44f2f09b236020324c4ff4688614246ca86e0100000000000000ce571a94661c993c3c9309d3ea50f655a55aef1114b548e5309a3f7d506de70b010000000000000042c56bdb09d52942b0fedb07045113a641e2fd64a428b1fa608b5adff9ff4d640100000000000000a0a5985a2d831cc21039cba304cc7da8512cc9098440896fe45ac6dbd8e6b3300100000000000000108c7ed0328d5b09c3f2800da3b8bcc812eda208e3ed636ea1d5a5f312cac56a0100000000000000be8c20cbf28d23f4ee2c82d16d92b7ffd15dbc8e3b64ece63a24ff703f30a07b0100000000000000f29cb4064a1cc3a79da2c9a9f336053cc69d50bcc737257ca2f071c37030510a010000000000000074ee45b1b895aa42f0ea4642cd50e29e43f741f607f25fd5be35ea8cfc9c1c1701000000000000001e23aea69748f8f1d4f9fbe21694942fb42df344e3e314c4a017a4026ac0d31101000000000000003e07b075219fc7ace8dc3bf3a06f5dc12aa9c7e45fe30244d2284bcfb1e6ee1901000000000000003eebdcb51baa53794fa06a4068cec848881ed9b400e1bf1e577d4815c69ba74101000000000000002271d61469f9f1e5a0832af7de453015b89979fd740526080116295f4a4a516d0100000000000000645077cf303943059891df150649d1d828052ea4249bf50ca3b6d29c6ef1984c0100000000000000a0168573a861e2576ab9c5d74d5a5c6e094e6e0261db290363fdb096da94786b010000000000000022376791bf19fefac611324d27bc6acb4b7f7eec713c186adbeda5a1e1b88f340100000000000000aa3463dd8ac73ea72ed500024f5b8bdcca5b20aa9ac557cb7cf980977f120064010000000000000066afec1ea0202d0623f3f92bd2c9e8b78dcbaf4ac7d5fdbe63dd41a79515806a0100000000000000bc8f93a45201992fa9d04355095d03adeb5ff1aea206425eae4f902ffd47fe20010000000000000034caa67978c1a5280b5f58196edcdb5c864b02d0fd40af9c6e6b9716f3fb12680100000000000000ea03f9dc29ae9b7a053c12b6079664592d2cf46a30b43edbb2d2d980223deb110100000000000000b20050395fc81aa60508e362f02c75faebe3e4909c7a23721182ce791bb7011301000000000000007cf1bdd921922cb281bbbeae6fc07218f1d47b73ad3f0f7902e9a7d86d705b080100000000000000526fdfd1d78345a1b2843d392122962cf89a4f157af2a3d0c99607f506175115010000000000000008e80cc5ada5e557a1cea3658402bc83f9892b5c4e112b6e157e6e7d3663c47b0100000000000000a6730d04d45ee4e7e25d3f7b80b4e2ac12a6644a4128127fbe97e97a1d690d69010000000000000068147c36d367eb1a203b303c65ab3d32fe777cabbca8d39e08ffcfd624b3614d0100000000000000b6ad9df8c32a78e9481e75f484fd0b740554276c026736f0dbac0987db08856701000000000000000a6a0f8136fafe5c2e096704e37d12b47a1e46151489a23eb1713b37769fdf780100000000000000281ab8d29fc2bf57650c90e6ab4966f050d4c5c74e94fa659a78bf1dfa71424b0100000000000000d083ff045870d501ac65c3b29384fe542bb53c20308fe740f261caed7ecb04410100000000000000c4687b6d8e527d1ad3be71f2b242bed92eac25b159d9e142e6922ace2dfe5f2101000000000000001437b1c354ee833e93db39ce7b54269c486db9ac4f5e6bce77216a04d7cc376c01000000000000009ea2cb3e6c59685087e59d6d45fdccdd5e6fd4f77fd90b4749f65113e23f086f0100000000000000cc60431feaf7f1bf42d805f0c12a1978ca9b3ec0a21397a71ecfc2bb7d52d20a01000000000000004a7791775365fadbb61f37a0d2f6d298c0c7c3a4c9402821ec909972fd5f8a4c0100000000000000fe3bbb52c1e1b9169ddd63b8f8d14f14d1f291fdac7387deac13e5ea1f8feb6c01000000000000001827754b7465edb9bf4ce981bdd3a33057f9450fc895e39654dbd51c3ab9835a0100000000000000ba099f95644de464c05e2359160bef3e682b8ef3bedc2d5f34fa1a575224645d010000000000000086666d009342994d248819055032a548e2a964da26184293bb9bcb84f5d5d05901000000000000004854cac0c8e7efba2bb24c236cf20212c5a1aeee9e22ea1c97f7b7f61993f81b010000000000000052978f35bc7dc9cd664d2224d164b8de42221e8e6942d66f47a5e9e95cc95d470100000000000000fedb0e6bb7420d16e7112167b894e2da0287b2a170ea43ac038dd416118e156e0100000000000000e0d28dc9623e77eeff6b0aee79793b3a00cf8b1c46fb79c8e6ff8cfeecc4af120100000000000000d0106f6fb9b008052da3223c389525681d9b6e4fdb73a4078f7f1949bfaa350201000000000000001e1f47deab3e4083f7d353b746b719a9f5aaee3ae2cf6b37a4d710f95d489a6101000000000000004a48e0f85fc8b22e74020e1efeed0e275653e8ecdf028c01f13384def95de92a0100000000000000725d8666c3eda2592bf0b16877cfe8e292f61f0456f1d30fd4c29dd05ef0922f010000000000000004601ba22158973d6bed9113f9976c7947daf458f58ae1943ff6f79553e8d4010100000000000000d4a87be02f6839b90794e3880e77ca40a53a7ebdba4a8a5a9c743acf79c7384c0100000000000000caf6489970c76d9f756bb0b914cbd8beca60312b1e210f9d46b6677b03dc86000100000000000000102ed4107066f497e13d3c484a9fa60e506587e19541069dd4555a91d63f27040100000000000000d27da69172c428ddb80272e6fc6ec90985ee281b45f933e5bad65184bc3b5d0201000000000000003afb6b0dac3a05453f125943b8a26269202d297b991e054ca851fa68bb4c08530100000000000000086b88822caebe9d73149400994a2df6cf317debccde56252bd6616cb28ad859010000000000000014a7dcff9114935084580b0b3f39c1260205e63ac607168795f5b0867f28f52601000000000000009e80c458262141e85c50db48c81b519e5eb97d400b66acaa7f47649e5c23b82801000000000000000c3292b5065b7b78a2de5f4fe397fff21df37c0ff7eef94c5fc4397f760e6e46010000000000000012030a66b25d1ddedf761e0875430a266c847b370aa64dc8c106e4b0b997283e01000000000000004616ac86f0d45899eed3f1246dc5744858a694a92b0abd9f10e52dfc9c28674601000000000000009265e7be28a8f56a974027b630bc37703b7ef21b1b1e4253c54d605f4d10da1e010000000000000046b14e55053a02087c957664d32fdcae6ba1c96051239191c63df564d784e1720100000000000000be2a3b6770dcdcda22736d6705a8d075b77544e73311fd0517058867f184ef32010000000000000058efa50da673a8c3b5799e278ae7d32f9eee340947f793f44348ba17e25a885f0100000000000000da5a8d123547810ba496f10294160840c6e067cca57643c9da68265321e80c2c0100000000000000908033d709f4315e38709b4fbcea1e79a9a91b06cd9d31b9d379b7c6232141750100000000000000de97aa69c9dc17083f2323fef768c1066d0c31e61fb1c57452c851f60569cb1e01000000000000009c4d874baeccbb19733cf93f6ffb2f44d9b9f5191ead84f3550c7b767a75061f0100000000000000d0f8b7532498f883c5c76e05a3c414609da9c82c254aa2bac8e8205d2a80682b01000000000000008ea25b46bbf10e124cdd2a34b2134ff31666a0db69fa2fd17794522b3fc6c5390100000000000000924bef00fa94a5c8d29e672c50c68829db4454a85fce54ed3fabd27b454dcf060100000000000000723f8c9d81d0874cd4130cb58587c90ef454174e9d6d9dec11279a553caf00430100000000000000bcc2dbaf82ccaa470212cf2bf8e87f0639bb9fa454c63878a0ad8c06e39a46650100000000000000547c6a159db6eb46da71179d0d15dad5691617fc7f3c6a672864655997035c2d010000000000000040884e6b9876fe866d109aae2a5a6f1a18bfe3655ec9c1fee848ca9273446872010000000000000045155a07a5a9f181b1ae2d8ffbcf54af9e12621b17dedf9b73058bd535484e6f01000000000000000400000000000000028edc0df46d8dd7b4d2976d124920bf94ab2bdd9058f837f3a502586a70d22ddbd24ddc00019d17000000000000733eaa10000000006009000000000000a50466f60202b962c40e58fcf3481f5773dc178b9fe096f81511eaa4c7bad20e612001000000000000009c40155989f6072e82caba245d7db7e40a60f866b403257976b89aba6be2b55b0100000000000000ee3b07c54f0d93945caa98d8deea125865e36dee14644453fb07176d4605bb2c010000000000000072ab87b654d80294c876cbefb534b3344c2f64159b015b89221331ec2145417501000000000000008e43fb54c6d8074ba65ddc6c1b9c54a9c9f0508ec939d5b1746ad2bc42069c600100000000000000e2782e5b1d9962dcb6c006b797af79017be14346a6c2086ff132776ee7e74f53010000000000000020352ba0565811731625a8001d26f5d899e5856dedd0f9c6bc3bec2995704e5b01000000000000004c9886e2e62ee92a6778d6a7928052732044b64fa61969cd8e37f3f7e3406f72010000000000000012f7e35aedc710f8335cc813db106f2a569c6224505416e33c241e625993a86a0100000000000000dceaa05fb95e70e99b9fcfa547a67d067b1ec24b1e795bcd739ff3fdf1c2c9160100000000000000002e496e564f088a075525d2f9155aadd1a7eb017fa36f9e16096e9db7e1693301000000000000006a49a129620f4318c4a99b69c28cbe5f94c7578bbce50bf2627c61590f68df750100000000000000f6dddaaaa53b57763610037753656b591d90fa81efbadcabbeddf7378c23602701000000000000009601c5f103f77e1cb78d4e03f2585320142cbb4fd6c5c37f21edbbb2d343eb560100000000000000466c0e97d043a4b0f4c3ac4849e11f901e9b31b28f8b3e40b7cdb0ba7f77480801000000000000002049288b4dbfb741109778c602f9308daf2e31b3b66e9aa550065e73c6787d7c0100000000000000e67c524e443cda4cd27dfcce70488a5d23a93c8c46a5e83ef5a69eff3a02fa5a0100000000000000ca4fb6a27ee4ba734e8e8caac9ed440170a99efe98af430a14a3eaa4b0d03d600100000000000000400c83c89f541c02338cf113c5a841d810bf3bf17c5c6e78efbd637059005f7001000000000000002e85d3d2c07aaf1c0a5f63f544c34b87cfa90a98c4f6167e86cee0b74a20cb1201000000000000007c5f58a83f8101943c089dba3ab906c07811e853444aa58dbcc986c4095fbe7c01000000000000005494142902284943201b7cf610306e8665eeeec87c014d607175c3f50f76103b01000000000000001822493200c35242a149070784dca5e7012a8a52b61cd218ec7d65e469e8cc560100000000000000dcf6d4dda860d902eb4acb8adff1116c637c12eb9d0633caa8fd0b65a30c8105010000000000000042e377034ce6b2a582bfd66c465252ab10ce790e4f0d3bbe99a42ff86b29965c010000000000000052e281ebf2cb6e1751a844d92574869e5a06e596bc41404de1fe55e99980dc6901000000000000004e2753547f6ec0a896bcbc55b9eeab875e8019acdeb10b979210af63f24c4b740100000000000000822467882ab8bd2cd75152843a948b3e56ae1da6aac9b66ac4cba1448217d8410100000000000000f63e0c859002c868d1e8bf7b36558b7b3f4a033f13850862ad643bc99628f335010000000000000090fd0815e122cc480aaa256b319405ab08f867d414dd59736bc81b7f054c59700100000000000000046c86bcf2260b9e862c5867def0e1a528c32e64ce0cb20d41bba00f30013a690100000000000000d416213c0b30df8f5aadf00642a4777dcea76b12836c51a98abcd133c78899470100000000000000ae831c0a4d22eeff12f679540c229029e321499477451768b8999b1191d6164801000000000000006ec27dfa7ac9d35eb002c55d3e4d56b4df928dd5c44323ac228305741c9e09360100000000000000b89cbc83a386d6f5d4fed93289ee50fdf69d77369ca0c9a8b962554e3fc0d37e0100000000000000e61da4eefdd14434952c58dd1943f7f63185d03321ccc8835e4216badd16fc19010000000000000078f66da37371586d480a8c4dcb2fc772c7c3c185961b5757169cb3b72c12436b0100000000000000a20797f3a8669a909adb22a3aee2844dba82d231cc33f5d9be0e2c533cb82a670100000000000000e297620b731b4958e3c6aa06611c6aa5a45f7e116362d64954a0a330d2a98f33010000000000000088c2166cef8e248c6dc7f801967f6c936b21ecff6f061035d9f95cbaabbcbb0f01000000000000005a7a6d3951924738f27fec8c0baa71a0f518a2d56d8289a1887d3d6805088c220100000000000000049e89e200ca2e92ee67afb644b216f3e99c8b4eaf26c1f0e42038850d0c617901000000000000004077191c8d78ed00c81b74788215db40d498f37252f9966f57e96c9d3f6af31701000000000000000ef6f09a9e310abb5c57dd7050a94d56d766772b80789b997cbb40f3b40f625d0100000000000000b25892ec76bcc88536409e440cb14f9de9589c4efe2b69608fff594885a2fe6501000000000000007cc03ffbfb187c1ea32cf4d25893238aae9073b2016084052a6defac64a7e36c01000000000000003af71b42b712323aa28fd7a2099c4f8b8071e3ed27c8a52ff2cdff5d1a5eb66b0100000000000000a88864a0dc9e292aa7cc8eddaa8dd8b6be2a4bc7e8f290023c6604e5c4ad1a7a0100000000000000dc68569b46a09aebabe8fc4452e293fac635e4a2889739809b32e4e2303e3f71010000000000000034ffee048e511f4187a6f40339650ec60a3d99ac5a1158ae162c5729b59d51740100000000000000be7c58318c49ff328d53a6d67830a8a046a41f5124824d3ce2e72cc9965ef57e0100000000000000a693f218033b3eb885bd2c7793227834d1ff3350c296e49aef3d8d801d5719750100000000000000b06e3ee1ea6420fb73ebd502988420f51b977a83074e1aa5daf0121f4a8b6b1e01000000000000003843abe933fa3ce63f3a5e422e13ec05dc9c0e8f150b93a0fa97f1b193cfba2d01000000000000009cdd57a06bd22d104d539527a19033620becff73dd267f0c2f9f13bc37b0d32c0100000000000000e020b5e946e4c6b0603ceac71b44c330fa7d9cb3e79791ebe1e16bedbb9c71000100000000000000a86c7bdf11794e554439b09f9f294c8e0abaebf447c7bc54419434b8b95f864901000000000000009e9f565a8cb6e8f2154a9833735930a04003505856c3743a0f71afe64c7acf71010000000000000042e4c41a899dfb238649e5b17dc232c2699353635d60e6a3bdcd71f9b82cda300100000000000000a24cc4a40afe5d37968f8d6c7904181a1390d5e718ad04a27ace2ea62f52376001000000000000002261bba26f785cfff606f086f5db420a43a4322fb9d225410a140acbe3d3a405010000000000000050a257ba8dddbf08556f5708bccb587ff4dfbfad15f217d422d7bcf2a7f7f5600100000000000000f23d1b22d1b03c9fb6eb203c85761fe429a60c38d6591d215e873d62f5d2e4010100000000000000283a77cab50b96f99a8e8287c1488ebbcf31fc3daa953ffa99ac16db982f1e12010000000000000094e80daa135f9283d6e8c00c00840ef766863b7d89f354c208b75062f9507c760100000000000000ee579514d7f544fc9fb8d6383ed7d109ee98a411bb4b0b45b9354b0f73fed9720100000000000000b8e999c053a20108e3380d6cb1c2dd2b8e6973c7b2a1f354ca91068c1c1eb83d0100000000000000e8308668e9f16683cc739791a6dd530b819f45e4ade2113ee2f27eed1c51d1200100000000000000b0b313e6391bd3cad2a2c91e4fdaff1404e8a5e2014e4ddbe89f0b7a63e28079010000000000000074b89b94bfe9d61d16ace3eacec820305edfa6a7286ada941e92cfb0bd8374100100000000000000b25eaa07b529a889d38e0346761842f8ca2e970b31038d174c88c7fb667718270100000000000000825e4307d8b2b4387bdadc97f6aa854152dcb5ea892bd1e6790afb1dd83e2e2d0100000000000000a889c98c4c129efe5ecf6e78992d19903205818ca2b760ec25a0b7debb7a2f18010000000000000026d421de2e7251020ac2f8b8c7e348aa904dcaf0b6d5d73fa0113b476f7dd903010000000000000020d5041fd7749a76b9862d74f365692ed6186dd95b0436df82089918920bc3580100000000000000bc56c07cea21bcbbe058aedd2ced9fb4757caead55f96bda9bed1c9669c32b640100000000000000ee1c578a2f792ff3237d645124391b6422b16724b1da5f1b4296f422834bf01c0100000000000000da5c9a8e3df09d9e2a73aa5453b53998b426fd747e887faeb9b2dc99a03cd12201000000000000006ccf2ce8e149999a7bb996faa65194e60aeb7bcd1937c787f886fe979fb49e66010000000000000082b820c5bee8ee77e35203dab387f3434b8502e5f1c35dfb2ad15b5c89d47b3c01000000000000003ef7b532bad1e78d67254bb738d2e5aa357aa04dece89ca3aeadcc8b77efe14b0100000000000000b6ea2250aca814c227ff53de081c337cfdbdef2eb3b0416555589fdc15cf64360100000000000000422318d2ed50f9e42bc2451394ea2faa9b6e0a2454d1471a8ad6ed7b2164b81b0100000000000000b4b145ce385b4a3d83f2daac46a61874f80e58c468dd624acc09a558be02c27d0100000000000000ccebbca14a079b3f6a61898b07592456869c753f951401dd3696788419b5952b0100000000000000d04077347325618eb5cef03729a157b910fac54ec7e344e65b6945fb9fbbeb3b0100000000000000069fc7b8027f7088057362a588ed9af23342e37b70fa163cb47897f7960025580100000000000000fe3b55d17e25c44a3568885d9d37276df81fa5225d9d73ee67321c7826581b5a0100000000000000dee6847832968c1e240c64eb4d2cfd8f5ff3be16d63301638049c8cc7db83059010000000000000040a2527ffa7d30d788eca127d435c8b5aa48972cda538b9a1627a57e85c8fa190100000000000000cebf2df4a8cae34e2f4c645863327db8a10b19119ab7d1cd887a4cb8acc0481101000000000000008ee9a6372d159dd413e241b3201ae4cb2ae8d05fe95fbe1e565d81000dc418750100000000000000261ac3229b4bb7a376c37f17e287b2eb596d3b478370b722b6b41443d870813201000000000000001a36d936f4692ac8387ac0ca1f051970ae480271e39fc134436b86b8ec83b25d01000000000000007886559a7121bd7f28b06ce499e0bc3de3d0adf1abc47c6e0461383c7098237f0100000000000000e03dd3bbb140ffa44e0cc0e1846967b03aecccac78f6e2e0a1fd3ac0d34f554a0100000000000000a8818217d40fd73cfb5c28b2402a2c6049fd17f99226f3331b6bf328688e3c4401000000000000007affcc9e0c86c66957afb75d760842bfd374949da725718c0bd3edbf6a1bd7310100000000000000eabcf59549db01c112376fd042e3ecf95b1b3b5ae8e0e744965cad5880bf9e0e010000000000000068d6533bda9e474fabac2aff0e1e6aa7ac48509802f7cd29b5a4badaba2bf37f0100000000000000fa76b5548c290e38efd3aeb5bb478de80b0e4d10b09b758e0b0f0971993e6b1c010000000000000004ba7eb24012b133b20a8021b603a1483c4a5b9ad3415a4d7ca2b1ad625719550100000000000000202e3405e49bb882f1d49efc4a4adc5b62dcc96ec18346a48aad5a510c189b500100000000000000dc02c19ac49087a2a0c5188af826e5ed6450f5041f00ee8e77bc01b12945ac0d01000000000000001ca57b22ae230979adc98a3aa05d47f1196c27eda66bb6125a868583fba6e5420100000000000000ea6acde5149e930af7bc3b17b7f0bdcf12dfd3dc3437f774f823bbeef420a97201000000000000002ea86a65c1e3749548d3c56eb537d21e1756895e35ca99a9019b8606c47bd214010000000000000014e2f25dd3376eb7978d413c14322704a2ff3d9c0c2971acdcdf9720c2c13d6b010000000000000014cf97e739cfd033c2828f25ad3f15e8f6ef62ba97dd74164e77e61eb85454260100000000000000eef6e320387caad3fa7bf295c60b85adf0a6f5a19144a4433e1841b4a72e07410100000000000000a07f151db53097c2da9dac4b2e0f194931a677a3ba99df0f3976e34409fd64760100000000000000809a2c451363ab14bb2272aa972a2b1a1de3386fe2bd47113ba4819d67b6fd6501000000000000004cc9ff5edb36e361b088b0eff52fc6e6559c1169ff87ccdb62503bceab7c7445010000000000000040dab7f2e50b7ccee4e3a6223ac09882654079b695b110ad6401558959c2360d010000000000000004065673fbef2c9dbd1b79088e0e3cd6e39784ebb792ede843d9e7988da85c4c0100000000000000fcd5f4c4fe11f20ad99dc8345b7dc5600caba5d5b7d3f499c3253c095152d45401000000000000009254313d03095e6b374e43addebc950956bcb34f2d11a9c557514c9991b3aa0d01000000000000001e825121b8beecb30e9962a555ce06b9e2c65fcf3b0023178556330d565bcb4c0100000000000000e06ae0c49573816e158f02c5263a7b167c2ff7bc5528b13c1cc5a2ad0a34da16010000000000000038b723ee73f8083592437eb9f2e436ad7b694dbaa7599d154a9e3e01b14b69040100000000000000042ca33fbebb9f50bd3ee55c6eef27124379729ce2670914d1a762ebd5ced55c0100000000000000aa819492e4d782526781e8f9001f93d2b9a23142886757ac932702930b9a991e01000000000000008c14a0d64bbb88f3546c49bafb1f6bbe3d59cb277af2fc97f19aee0b80bdad0e01000000000000006834aee6fa1c48e229ad7431b77181ff03dedfa486aac6eb7880ec9950c445540100000000000000b48cf50a4f94e83450a791d6de965c3e8127c1c915208f2b85df4c3a84b2042f0100000000000000c60a9f5f89ea3a56499bcd39bac7e038c25f5b7720d873fdc12b68d2531eb650010000000000000040b77fd8fcabe868dc7f2a08bf14c67e4d433886c3cd3738d1b0b9c649bafc2301000000000000008c43dc50f9ed5bc7be6b4a648957ee5b01a2cbbf967077a6044d4b92f2c715070100000000000000fa81c1b7635c3f695915443a2dfc030e980cae09e592f555edb67436aa11215001000000000000001296762372530d2ccabddcbd204fa90217ce28c9365c5cf4a4eb9f46545b786a0100000000000000fe621d474a018c4e2265c864e994a129614dfb473339453f45a5510587d0174b0100000000000000f2b63387ce5b649f9388fd1be38ee4357b48dc0146e78b91f8f6469a78dc9f580100000000000000b2ba57f89fba50ab178f10f10f2ff79f6061cfec808679868eb7ddd8b08031340100000000000000e694e453023e9989a59e414a8783f9269e933574332c77067fa7ec2b9b6876100100000000000000dc702f22412e64b699d65c66ea2d0857e7b94c0448346f86068e658fc00c5a2c0100000000000000ccb4e6006ac696d5050bc790beff6eaf61a5dbee1a070f66c824b962fe177b6901000000000000009acfd215519f40156749868afc8d56e015759f71cf183fe68382e8c02c75b251010000000000000038f3f4c693034fb614c804ef2854850286df0b1411e5a0c83513ef4c4fa487050100000000000000de5f9f5ad3209502cf429630c2038b8818b6f8ce5685c2730077349802c579250100000000000000649d1a54b0a158350238c017a71aae21e3bb73497187a010d97e1e1b21e43b6401000000000000001cbfaf2b91ee79c6288ad01dd5787070b34d5e1b8253a1765904eaa7d0b93f02010000000000000036a547b4aca95274437f3876bec0447f775eacd01b09d95869390d326a596d450100000000000000a811667da1a12b408e2eddd3fe118403e1f8926b703104fe34193b4fca229d5701000000000000008e83fc9e157adcb687b4b994326f6de340d80075bdbb590eeaa3f29f457ef3560100000000000000b2afe6968bf90de3f8cea025a2b2b0b560b1899fd23343e52c778ab45e1f685f010000000000000026f2af62a2f0d847e3d2cccc93ec7f98c80a7b6d1bcca4cf1c4a6fc7f81775010100000000000000aafb720e50ac6fe69aa177dff62a733a0e98cc0fe7c35e591127479e7e94d5430100000000000000a8f7368dec8f4f30db015c4362e03cd588c6e60f2f4f69912ee4aafb35df38620100000000000000e6767e8c251c74826054421ff499297c13ab6a4e84ce10e0dfae4e21b64aca7301000000000000000481a58bfdafecabbc96bd170a0ec04cc35100f1f928cca3ecc63b3639e47679010000000000000056935ed80a27ac471336a7c5a8b0e73432ddabdf5fe8992390cbae33a020883601000000000000008ec5856a5fd17617c0af76efea16a87d0c5e769eaad39e91c40dac93fb067d5d0100000000000000b0d7d82ba2eca517d6d899525672a1d236f907565785e41ba80296aad19dc57f0100000000000000e4be18b8f5905bc41fe3cba2e5350d405e76036328042ae7edfbb6b6a9b43d5a010000000000000038a69f047c05d50988318a333c2a6bdde4b778592d66328bcf44f1472c1dab500100000000000000b28eace0661acec97215230b9aae3c2be19ef43e9eb90554ab44b51c6180362001000000000000004ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b1402010000000000000036b1aeb61d78c234c0448c0622c570c33ad8fa7b5d7d12102ab323b7985d31690100000000000000a6cfacf0aff2d5c6e8eadf71f397a64f2863e5f0b8793e3068aebd5b3030e13101000000000000007eb2b0b6adbe5a5bad38f46db207f94c896d419661f4ab8f21e302a543df9b1101000000000000004014ed541e698a7a87888c6b5f0c54d74de28c8cd3bd8f1b1f8fd7fdb757cf330100000000000000b032afc9e8d2abc223f23c1d1e1776b3c66a23f5917a7669d69c2eda81b08c3e010000000000000048ce0aba6f1554e139568b4d2358d6cca9bc291d3600787cc3e732291002ca22010000000000000092239fbae2557ff2ea3952c962e478e6ac2a5b3e3cfffb0eb40e8d41860ab0470100000000000000e82715ac0ec2e1f41af952f272f20ef2d2ef826c441c6f33a95522270e57db4b0100000000000000469d81e8b43725a64da6b1ce10eb53eebe1aaebb9703f75ed452e12f45d262730100000000000000285987285ceda1670b1a2fc5c5cf8578a368d63aabfdbbee83ea05db6ae376470100000000000000c4f22a0641190f1bceebea3f8280f22469d6ac0d9b27bcab27d778ac517d2479010000000000000026106dc6fa26823ed60e52e0b1a164dd897be2f617bbf24ddebd9ab34bf6de7701000000000000001c71bcb434190e911175317142b8589619ea3087fb2048a9117607b7b11d11300100000000000000a8527842f1040269688813eb1cf64f525cac5f9219feac35b2d46bcd2df52d100100000000000000a670be090a366ff66d8f7d1eabb7514252222507111e53430bd437a8dbe53a52010000000000000018261ac5151f160bc419a8e44d85fbd4cd8669decacb23c8d7f36f316cbb445e0100000000000000fc53d15453457faadc5540c5853f54324eec395d3647fbf99d5e6e97ef3876760100000000000000544d12f359dbe87200565a9697af85b936a1b5f9d0a363f2ee540ec544aa761e0100000000000000fca464b97dee2e318ad8d4516fd606a5401f5d15467110112a3326ef96ce00760100000000000000864cbd281011a154d93d0320865ad67ae442bf0985f0ec220e2c7db4b095993101000000000000004c696de688ef5d4d5899d1e596a81fde52db76757669bd0051a155fb2335ed0e0100000000000000382fb32d7c8868ce3765e9ccfb462c04071a3d70cab3382c796a9115ab0c310301000000000000008a6dbf87f769167b4eb982f63b946f96a1f223b6a6f2789183fec09581b8e9060100000000000000b027ae418b6c79d9f3a2b05df499d3aaecfb327e6b9d7995a022dc5265ed76180100000000000000eed7e8e8a64dfa89c548a31c1b9fec7af5aef4dbbdb26997b2ddca72d4f8790c0100000000000000a811cc491bb3487d5e604dcf6dca3bf529437162f3b8cfb8514ffab16809ff600100000000000000fe2848018ac215f72f551e58dd2d065d99b788b5a7aa59b9f9fe47a5bdbc046d0100000000000000b6ed5b0c17ca7560c71f1778694741009d3da979309617f0bb992084019e25290100000000000000f853a1534a3af56217661420536dd7bea0db6f6db843d8fead77c308ed7dcc7c010000000000000004b0ff0440c7e131b891a3c13c6f7f0233dbe80fe90dc097f8c5566f2bb49a5f01000000000000005af4895ad43e058a09b4982b8c78021f1ae6cdec9f6633089f32e948ef0d2a11010000000000000028702457fd7ea52bb88284bfcd721493ceae3ea984492a1b82c55efa1b62fa39010000000000000036550a8edfcf14f96e29a7901f5610b57722dbd68b48608572e98468c5bc1f6901000000000000008a51ec3cd1c7e1e5cdc0e3697dd028337ba54e18169cbb241140dbdcc928695c0100000000000000c80832d979a4ba72f7179c346fe660490c292689da81d790baa30a76b598ad5601000000000000006ef86d4533f47ffd133c63b9575c17234309ab6e16f487ae7cd8914169183c66010000000000000056606b6532cdbf27358fd067d61c2a65e4b3e8934c266a857320ff18e5c7654c01000000000000006e8ab85645445eed3828ed583d9a0af03a682fea56d16f833970a3289088e2510100000000000000d096cea7ac5f1bbcaad09ed4723a23fa3b582cc352182a49f8e4511acfa6f87a0100000000000000481ef876bba4865bb88d141606632b3a482c4e5c58c9c30786f6a279eea8a7780100000000000000f403ea18b9e4e9075319b30bf6b6201dd90d012fe4ba28a1c759d0822b9e550901000000000000000690823277fbe96c145c1686519038d301d63bad07d343810506e2cad4b1145701000000000000006c06a116c1a75e2e3b46a7924fe23ca8d58d2a32acac4ca8d0a1e23e3b4c4720010000000000000094d89cb8df2b03c76d41a6521e5803d6f98e204e1839b9ea747dc7e253d35b7f01000000000000009ce314a687a2e8754e1351cda727fdc20e473c08c8bcf5cb70c9a048b571540301000000000000002801cda4aec5f013c3eb504100b1e29e0e65423219d7c6b1b48b0a424a42307c0100000000000000ccb5a9652f3be5d85fcab3d0b8c2eae27519ae2f7befa40c34b89751bbcce40001000000000000005258f48e31bc89f5d53ea6a12eea9698f8e72c6068ac1588100d8632bc674d1e010000000000000094de02a2418c67e938e449c2297944e13cf638e67110299f14cafd5bf2fc60140100000000000000540926fefa2d0424fd451bfca39a01c0e1a3fc811406e127d1dbfdc6cf9e9770010000000000000038c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e85290100000000000000a0b7bf06b6c030493f2107c1f2c4154b98b677fcfd461e5817b909f31223a5630100000000000000eab9946bb96a047e9c2fb0e6db8236e46192bcced0c8ea7319142a73cfaf000401000000000000009a53749c83cc06460148d884f1ea5b71897466b237cf16baa45395d78ce48c1a0100000000000000f46eb7a2664580b8655261ad48df75d27404fa23ec47012148dca3c48783bc39010000000000000088fa8bb07ebce99964718c65d0d6f1b091ef2f4d4cdf7b94a22c42c007ecd70601000000000000008a0e2d0af87ffb812f6e6ec229d02056e812cc4f5f5743cc638a7d3f279f0153010000000000000092e5bb9d0906f768dbdde0696b78e493cc78dc1f68789575b24f0b962799b51e01000000000000001ab9d2c814ed7a719ef2aa94dcf4db8aaa0315a59d4b5699e86656a6ee9ac5610100000000000000b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d010000000000000010e37a12fc6ed768d1a2d33c8abc6db675381dfe69c832abb77d9ba2341b3c4a0100000000000000bc62cca37518b73aa22efed6a88147f84af5db7b82ef7671d9bbf03c76d22b4901000000000000000e21a03fbe9885a475c4875f3f912c8703945e99cd2a85f75258fda7b6022b7c0100000000000000206cc2601e4cc1c4d543c1f22eeabb29d72dba4e47630882b2c783e6d3d1935401000000000000002ef372f7d4c71a60f76f65c8ba860ccdf38a85db80963c7f569990ae3865cd470100000000000000068ea8205451f7fdfc6e72059bc58f56cfbd2edcf349f3514de9b00d0c54856801000000000000000e973b21dcbf05732a16fbb925cc44f2f09b236020324c4ff4688614246ca86e0100000000000000ce571a94661c993c3c9309d3ea50f655a55aef1114b548e5309a3f7d506de70b010000000000000042c56bdb09d52942b0fedb07045113a641e2fd64a428b1fa608b5adff9ff4d640100000000000000a0a5985a2d831cc21039cba304cc7da8512cc9098440896fe45ac6dbd8e6b3300100000000000000108c7ed0328d5b09c3f2800da3b8bcc812eda208e3ed636ea1d5a5f312cac56a0100000000000000be8c20cbf28d23f4ee2c82d16d92b7ffd15dbc8e3b64ece63a24ff703f30a07b0100000000000000f29cb4064a1cc3a79da2c9a9f336053cc69d50bcc737257ca2f071c37030510a010000000000000074ee45b1b895aa42f0ea4642cd50e29e43f741f607f25fd5be35ea8cfc9c1c1701000000000000001e23aea69748f8f1d4f9fbe21694942fb42df344e3e314c4a017a4026ac0d31101000000000000003e07b075219fc7ace8dc3bf3a06f5dc12aa9c7e45fe30244d2284bcfb1e6ee1901000000000000003eebdcb51baa53794fa06a4068cec848881ed9b400e1bf1e577d4815c69ba74101000000000000002271d61469f9f1e5a0832af7de453015b89979fd740526080116295f4a4a516d0100000000000000645077cf303943059891df150649d1d828052ea4249bf50ca3b6d29c6ef1984c0100000000000000a0168573a861e2576ab9c5d74d5a5c6e094e6e0261db290363fdb096da94786b010000000000000022376791bf19fefac611324d27bc6acb4b7f7eec713c186adbeda5a1e1b88f340100000000000000aa3463dd8ac73ea72ed500024f5b8bdcca5b20aa9ac557cb7cf980977f120064010000000000000066afec1ea0202d0623f3f92bd2c9e8b78dcbaf4ac7d5fdbe63dd41a79515806a0100000000000000bc8f93a45201992fa9d04355095d03adeb5ff1aea206425eae4f902ffd47fe20010000000000000034caa67978c1a5280b5f58196edcdb5c864b02d0fd40af9c6e6b9716f3fb12680100000000000000ea03f9dc29ae9b7a053c12b6079664592d2cf46a30b43edbb2d2d980223deb110100000000000000b20050395fc81aa60508e362f02c75faebe3e4909c7a23721182ce791bb7011301000000000000007cf1bdd921922cb281bbbeae6fc07218f1d47b73ad3f0f7902e9a7d86d705b080100000000000000526fdfd1d78345a1b2843d392122962cf89a4f157af2a3d0c99607f506175115010000000000000008e80cc5ada5e557a1cea3658402bc83f9892b5c4e112b6e157e6e7d3663c47b0100000000000000a6730d04d45ee4e7e25d3f7b80b4e2ac12a6644a4128127fbe97e97a1d690d69010000000000000068147c36d367eb1a203b303c65ab3d32fe777cabbca8d39e08ffcfd624b3614d0100000000000000b6ad9df8c32a78e9481e75f484fd0b740554276c026736f0dbac0987db08856701000000000000000a6a0f8136fafe5c2e096704e37d12b47a1e46151489a23eb1713b37769fdf780100000000000000281ab8d29fc2bf57650c90e6ab4966f050d4c5c74e94fa659a78bf1dfa71424b0100000000000000d083ff045870d501ac65c3b29384fe542bb53c20308fe740f261caed7ecb04410100000000000000c4687b6d8e527d1ad3be71f2b242bed92eac25b159d9e142e6922ace2dfe5f2101000000000000001437b1c354ee833e93db39ce7b54269c486db9ac4f5e6bce77216a04d7cc376c01000000000000009ea2cb3e6c59685087e59d6d45fdccdd5e6fd4f77fd90b4749f65113e23f086f0100000000000000cc60431feaf7f1bf42d805f0c12a1978ca9b3ec0a21397a71ecfc2bb7d52d20a01000000000000004a7791775365fadbb61f37a0d2f6d298c0c7c3a4c9402821ec909972fd5f8a4c0100000000000000fe3bbb52c1e1b9169ddd63b8f8d14f14d1f291fdac7387deac13e5ea1f8feb6c01000000000000001827754b7465edb9bf4ce981bdd3a33057f9450fc895e39654dbd51c3ab9835a0100000000000000ba099f95644de464c05e2359160bef3e682b8ef3bedc2d5f34fa1a575224645d010000000000000086666d009342994d248819055032a548e2a964da26184293bb9bcb84f5d5d05901000000000000004854cac0c8e7efba2bb24c236cf20212c5a1aeee9e22ea1c97f7b7f61993f81b010000000000000052978f35bc7dc9cd664d2224d164b8de42221e8e6942d66f47a5e9e95cc95d470100000000000000fedb0e6bb7420d16e7112167b894e2da0287b2a170ea43ac038dd416118e156e0100000000000000e0d28dc9623e77eeff6b0aee79793b3a00cf8b1c46fb79c8e6ff8cfeecc4af120100000000000000d0106f6fb9b008052da3223c389525681d9b6e4fdb73a4078f7f1949bfaa350201000000000000001e1f47deab3e4083f7d353b746b719a9f5aaee3ae2cf6b37a4d710f95d489a6101000000000000004a48e0f85fc8b22e74020e1efeed0e275653e8ecdf028c01f13384def95de92a0100000000000000725d8666c3eda2592bf0b16877cfe8e292f61f0456f1d30fd4c29dd05ef0922f010000000000000004601ba22158973d6bed9113f9976c7947daf458f58ae1943ff6f79553e8d4010100000000000000d4a87be02f6839b90794e3880e77ca40a53a7ebdba4a8a5a9c743acf79c7384c0100000000000000caf6489970c76d9f756bb0b914cbd8beca60312b1e210f9d46b6677b03dc86000100000000000000102ed4107066f497e13d3c484a9fa60e506587e19541069dd4555a91d63f27040100000000000000d27da69172c428ddb80272e6fc6ec90985ee281b45f933e5bad65184bc3b5d0201000000000000003afb6b0dac3a05453f125943b8a26269202d297b991e054ca851fa68bb4c08530100000000000000086b88822caebe9d73149400994a2df6cf317debccde56252bd6616cb28ad859010000000000000014a7dcff9114935084580b0b3f39c1260205e63ac607168795f5b0867f28f52601000000000000009e80c458262141e85c50db48c81b519e5eb97d400b66acaa7f47649e5c23b82801000000000000000c3292b5065b7b78a2de5f4fe397fff21df37c0ff7eef94c5fc4397f760e6e46010000000000000012030a66b25d1ddedf761e0875430a266c847b370aa64dc8c106e4b0b997283e01000000000000004616ac86f0d45899eed3f1246dc5744858a694a92b0abd9f10e52dfc9c28674601000000000000009265e7be28a8f56a974027b630bc37703b7ef21b1b1e4253c54d605f4d10da1e010000000000000046b14e55053a02087c957664d32fdcae6ba1c96051239191c63df564d784e1720100000000000000be2a3b6770dcdcda22736d6705a8d075b77544e73311fd0517058867f184ef32010000000000000058efa50da673a8c3b5799e278ae7d32f9eee340947f793f44348ba17e25a885f0100000000000000da5a8d123547810ba496f10294160840c6e067cca57643c9da68265321e80c2c0100000000000000908033d709f4315e38709b4fbcea1e79a9a91b06cd9d31b9d379b7c6232141750100000000000000de97aa69c9dc17083f2323fef768c1066d0c31e61fb1c57452c851f60569cb1e01000000000000009c4d874baeccbb19733cf93f6ffb2f44d9b9f5191ead84f3550c7b767a75061f0100000000000000d0f8b7532498f883c5c76e05a3c414609da9c82c254aa2bac8e8205d2a80682b01000000000000008ea25b46bbf10e124cdd2a34b2134ff31666a0db69fa2fd17794522b3fc6c5390100000000000000924bef00fa94a5c8d29e672c50c68829db4454a85fce54ed3fabd27b454dcf060100000000000000723f8c9d81d0874cd4130cb58587c90ef454174e9d6d9dec11279a553caf00430100000000000000bcc2dbaf82ccaa470212cf2bf8e87f0639bb9fa454c63878a0ad8c06e39a46650100000000000000547c6a159db6eb46da71179d0d15dad5691617fc7f3c6a672864655997035c2d010000000000000040884e6b9876fe866d109aae2a5a6f1a18bfe3655ec9c1fee848ca927344687201000000000000005fa8097d55fa093fc48a7478a0f8681a08c5516068765f866f4fbabb89a9906601000000000000000400000000000000029a41a36f474af1af3046324e211e0edba2f8cc50390dff82976981bbd67245db2957dc00019e17000000000000d347aa10000000006009000000000000a50466f60202b962c40e58fcf3481f5773dc178b9fe096f81511eaa4c7bad20e612001000000000000009c40155989f6072e82caba245d7db7e40a60f866b403257976b89aba6be2b55b0100000000000000ee3b07c54f0d93945caa98d8deea125865e36dee14644453fb07176d4605bb2c010000000000000072ab87b654d80294c876cbefb534b3344c2f64159b015b89221331ec2145417501000000000000008e43fb54c6d8074ba65ddc6c1b9c54a9c9f0508ec939d5b1746ad2bc42069c600100000000000000e2782e5b1d9962dcb6c006b797af79017be14346a6c2086ff132776ee7e74f53010000000000000020352ba0565811731625a8001d26f5d899e5856dedd0f9c6bc3bec2995704e5b01000000000000004c9886e2e62ee92a6778d6a7928052732044b64fa61969cd8e37f3f7e3406f72010000000000000012f7e35aedc710f8335cc813db106f2a569c6224505416e33c241e625993a86a0100000000000000dceaa05fb95e70e99b9fcfa547a67d067b1ec24b1e795bcd739ff3fdf1c2c9160100000000000000002e496e564f088a075525d2f9155aadd1a7eb017fa36f9e16096e9db7e1693301000000000000006a49a129620f4318c4a99b69c28cbe5f94c7578bbce50bf2627c61590f68df750100000000000000f6dddaaaa53b57763610037753656b591d90fa81efbadcabbeddf7378c23602701000000000000009601c5f103f77e1cb78d4e03f2585320142cbb4fd6c5c37f21edbbb2d343eb560100000000000000466c0e97d043a4b0f4c3ac4849e11f901e9b31b28f8b3e40b7cdb0ba7f77480801000000000000002049288b4dbfb741109778c602f9308daf2e31b3b66e9aa550065e73c6787d7c0100000000000000e67c524e443cda4cd27dfcce70488a5d23a93c8c46a5e83ef5a69eff3a02fa5a0100000000000000ca4fb6a27ee4ba734e8e8caac9ed440170a99efe98af430a14a3eaa4b0d03d600100000000000000400c83c89f541c02338cf113c5a841d810bf3bf17c5c6e78efbd637059005f7001000000000000002e85d3d2c07aaf1c0a5f63f544c34b87cfa90a98c4f6167e86cee0b74a20cb1201000000000000007c5f58a83f8101943c089dba3ab906c07811e853444aa58dbcc986c4095fbe7c01000000000000005494142902284943201b7cf610306e8665eeeec87c014d607175c3f50f76103b01000000000000001822493200c35242a149070784dca5e7012a8a52b61cd218ec7d65e469e8cc560100000000000000dcf6d4dda860d902eb4acb8adff1116c637c12eb9d0633caa8fd0b65a30c8105010000000000000042e377034ce6b2a582bfd66c465252ab10ce790e4f0d3bbe99a42ff86b29965c010000000000000052e281ebf2cb6e1751a844d92574869e5a06e596bc41404de1fe55e99980dc6901000000000000004e2753547f6ec0a896bcbc55b9eeab875e8019acdeb10b979210af63f24c4b740100000000000000822467882ab8bd2cd75152843a948b3e56ae1da6aac9b66ac4cba1448217d8410100000000000000f63e0c859002c868d1e8bf7b36558b7b3f4a033f13850862ad643bc99628f335010000000000000090fd0815e122cc480aaa256b319405ab08f867d414dd59736bc81b7f054c59700100000000000000046c86bcf2260b9e862c5867def0e1a528c32e64ce0cb20d41bba00f30013a690100000000000000d416213c0b30df8f5aadf00642a4777dcea76b12836c51a98abcd133c78899470100000000000000ae831c0a4d22eeff12f679540c229029e321499477451768b8999b1191d6164801000000000000006ec27dfa7ac9d35eb002c55d3e4d56b4df928dd5c44323ac228305741c9e09360100000000000000b89cbc83a386d6f5d4fed93289ee50fdf69d77369ca0c9a8b962554e3fc0d37e0100000000000000e61da4eefdd14434952c58dd1943f7f63185d03321ccc8835e4216badd16fc19010000000000000078f66da37371586d480a8c4dcb2fc772c7c3c185961b5757169cb3b72c12436b0100000000000000a20797f3a8669a909adb22a3aee2844dba82d231cc33f5d9be0e2c533cb82a670100000000000000e297620b731b4958e3c6aa06611c6aa5a45f7e116362d64954a0a330d2a98f33010000000000000088c2166cef8e248c6dc7f801967f6c936b21ecff6f061035d9f95cbaabbcbb0f01000000000000005a7a6d3951924738f27fec8c0baa71a0f518a2d56d8289a1887d3d6805088c220100000000000000049e89e200ca2e92ee67afb644b216f3e99c8b4eaf26c1f0e42038850d0c617901000000000000004077191c8d78ed00c81b74788215db40d498f37252f9966f57e96c9d3f6af31701000000000000000ef6f09a9e310abb5c57dd7050a94d56d766772b80789b997cbb40f3b40f625d0100000000000000b25892ec76bcc88536409e440cb14f9de9589c4efe2b69608fff594885a2fe6501000000000000007cc03ffbfb187c1ea32cf4d25893238aae9073b2016084052a6defac64a7e36c01000000000000003af71b42b712323aa28fd7a2099c4f8b8071e3ed27c8a52ff2cdff5d1a5eb66b0100000000000000a88864a0dc9e292aa7cc8eddaa8dd8b6be2a4bc7e8f290023c6604e5c4ad1a7a0100000000000000dc68569b46a09aebabe8fc4452e293fac635e4a2889739809b32e4e2303e3f71010000000000000034ffee048e511f4187a6f40339650ec60a3d99ac5a1158ae162c5729b59d51740100000000000000be7c58318c49ff328d53a6d67830a8a046a41f5124824d3ce2e72cc9965ef57e0100000000000000a693f218033b3eb885bd2c7793227834d1ff3350c296e49aef3d8d801d5719750100000000000000b06e3ee1ea6420fb73ebd502988420f51b977a83074e1aa5daf0121f4a8b6b1e01000000000000003843abe933fa3ce63f3a5e422e13ec05dc9c0e8f150b93a0fa97f1b193cfba2d01000000000000009cdd57a06bd22d104d539527a19033620becff73dd267f0c2f9f13bc37b0d32c0100000000000000e020b5e946e4c6b0603ceac71b44c330fa7d9cb3e79791ebe1e16bedbb9c71000100000000000000a86c7bdf11794e554439b09f9f294c8e0abaebf447c7bc54419434b8b95f864901000000000000009e9f565a8cb6e8f2154a9833735930a04003505856c3743a0f71afe64c7acf71010000000000000042e4c41a899dfb238649e5b17dc232c2699353635d60e6a3bdcd71f9b82cda300100000000000000a24cc4a40afe5d37968f8d6c7904181a1390d5e718ad04a27ace2ea62f52376001000000000000002261bba26f785cfff606f086f5db420a43a4322fb9d225410a140acbe3d3a405010000000000000050a257ba8dddbf08556f5708bccb587ff4dfbfad15f217d422d7bcf2a7f7f5600100000000000000f23d1b22d1b03c9fb6eb203c85761fe429a60c38d6591d215e873d62f5d2e4010100000000000000283a77cab50b96f99a8e8287c1488ebbcf31fc3daa953ffa99ac16db982f1e12010000000000000094e80daa135f9283d6e8c00c00840ef766863b7d89f354c208b75062f9507c760100000000000000ee579514d7f544fc9fb8d6383ed7d109ee98a411bb4b0b45b9354b0f73fed9720100000000000000b8e999c053a20108e3380d6cb1c2dd2b8e6973c7b2a1f354ca91068c1c1eb83d0100000000000000e8308668e9f16683cc739791a6dd530b819f45e4ade2113ee2f27eed1c51d1200100000000000000b0b313e6391bd3cad2a2c91e4fdaff1404e8a5e2014e4ddbe89f0b7a63e28079010000000000000074b89b94bfe9d61d16ace3eacec820305edfa6a7286ada941e92cfb0bd8374100100000000000000b25eaa07b529a889d38e0346761842f8ca2e970b31038d174c88c7fb667718270100000000000000825e4307d8b2b4387bdadc97f6aa854152dcb5ea892bd1e6790afb1dd83e2e2d0100000000000000a889c98c4c129efe5ecf6e78992d19903205818ca2b760ec25a0b7debb7a2f18010000000000000026d421de2e7251020ac2f8b8c7e348aa904dcaf0b6d5d73fa0113b476f7dd903010000000000000020d5041fd7749a76b9862d74f365692ed6186dd95b0436df82089918920bc3580100000000000000bc56c07cea21bcbbe058aedd2ced9fb4757caead55f96bda9bed1c9669c32b640100000000000000ee1c578a2f792ff3237d645124391b6422b16724b1da5f1b4296f422834bf01c0100000000000000da5c9a8e3df09d9e2a73aa5453b53998b426fd747e887faeb9b2dc99a03cd12201000000000000006ccf2ce8e149999a7bb996faa65194e60aeb7bcd1937c787f886fe979fb49e66010000000000000082b820c5bee8ee77e35203dab387f3434b8502e5f1c35dfb2ad15b5c89d47b3c01000000000000003ef7b532bad1e78d67254bb738d2e5aa357aa04dece89ca3aeadcc8b77efe14b0100000000000000b6ea2250aca814c227ff53de081c337cfdbdef2eb3b0416555589fdc15cf64360100000000000000422318d2ed50f9e42bc2451394ea2faa9b6e0a2454d1471a8ad6ed7b2164b81b0100000000000000b4b145ce385b4a3d83f2daac46a61874f80e58c468dd624acc09a558be02c27d0100000000000000ccebbca14a079b3f6a61898b07592456869c753f951401dd3696788419b5952b0100000000000000d04077347325618eb5cef03729a157b910fac54ec7e344e65b6945fb9fbbeb3b0100000000000000069fc7b8027f7088057362a588ed9af23342e37b70fa163cb47897f7960025580100000000000000fe3b55d17e25c44a3568885d9d37276df81fa5225d9d73ee67321c7826581b5a0100000000000000dee6847832968c1e240c64eb4d2cfd8f5ff3be16d63301638049c8cc7db83059010000000000000040a2527ffa7d30d788eca127d435c8b5aa48972cda538b9a1627a57e85c8fa190100000000000000cebf2df4a8cae34e2f4c645863327db8a10b19119ab7d1cd887a4cb8acc0481101000000000000008ee9a6372d159dd413e241b3201ae4cb2ae8d05fe95fbe1e565d81000dc418750100000000000000261ac3229b4bb7a376c37f17e287b2eb596d3b478370b722b6b41443d870813201000000000000001a36d936f4692ac8387ac0ca1f051970ae480271e39fc134436b86b8ec83b25d01000000000000007886559a7121bd7f28b06ce499e0bc3de3d0adf1abc47c6e0461383c7098237f0100000000000000e03dd3bbb140ffa44e0cc0e1846967b03aecccac78f6e2e0a1fd3ac0d34f554a0100000000000000a8818217d40fd73cfb5c28b2402a2c6049fd17f99226f3331b6bf328688e3c4401000000000000007affcc9e0c86c66957afb75d760842bfd374949da725718c0bd3edbf6a1bd7310100000000000000eabcf59549db01c112376fd042e3ecf95b1b3b5ae8e0e744965cad5880bf9e0e010000000000000068d6533bda9e474fabac2aff0e1e6aa7ac48509802f7cd29b5a4badaba2bf37f0100000000000000fa76b5548c290e38efd3aeb5bb478de80b0e4d10b09b758e0b0f0971993e6b1c010000000000000004ba7eb24012b133b20a8021b603a1483c4a5b9ad3415a4d7ca2b1ad625719550100000000000000202e3405e49bb882f1d49efc4a4adc5b62dcc96ec18346a48aad5a510c189b500100000000000000dc02c19ac49087a2a0c5188af826e5ed6450f5041f00ee8e77bc01b12945ac0d01000000000000001ca57b22ae230979adc98a3aa05d47f1196c27eda66bb6125a868583fba6e5420100000000000000ea6acde5149e930af7bc3b17b7f0bdcf12dfd3dc3437f774f823bbeef420a97201000000000000002ea86a65c1e3749548d3c56eb537d21e1756895e35ca99a9019b8606c47bd214010000000000000014e2f25dd3376eb7978d413c14322704a2ff3d9c0c2971acdcdf9720c2c13d6b010000000000000014cf97e739cfd033c2828f25ad3f15e8f6ef62ba97dd74164e77e61eb85454260100000000000000eef6e320387caad3fa7bf295c60b85adf0a6f5a19144a4433e1841b4a72e07410100000000000000a07f151db53097c2da9dac4b2e0f194931a677a3ba99df0f3976e34409fd64760100000000000000809a2c451363ab14bb2272aa972a2b1a1de3386fe2bd47113ba4819d67b6fd6501000000000000004cc9ff5edb36e361b088b0eff52fc6e6559c1169ff87ccdb62503bceab7c7445010000000000000040dab7f2e50b7ccee4e3a6223ac09882654079b695b110ad6401558959c2360d010000000000000004065673fbef2c9dbd1b79088e0e3cd6e39784ebb792ede843d9e7988da85c4c0100000000000000fcd5f4c4fe11f20ad99dc8345b7dc5600caba5d5b7d3f499c3253c095152d45401000000000000009254313d03095e6b374e43addebc950956bcb34f2d11a9c557514c9991b3aa0d01000000000000001e825121b8beecb30e9962a555ce06b9e2c65fcf3b0023178556330d565bcb4c0100000000000000e06ae0c49573816e158f02c5263a7b167c2ff7bc5528b13c1cc5a2ad0a34da16010000000000000038b723ee73f8083592437eb9f2e436ad7b694dbaa7599d154a9e3e01b14b69040100000000000000042ca33fbebb9f50bd3ee55c6eef27124379729ce2670914d1a762ebd5ced55c0100000000000000aa819492e4d782526781e8f9001f93d2b9a23142886757ac932702930b9a991e01000000000000008c14a0d64bbb88f3546c49bafb1f6bbe3d59cb277af2fc97f19aee0b80bdad0e01000000000000006834aee6fa1c48e229ad7431b77181ff03dedfa486aac6eb7880ec9950c445540100000000000000b48cf50a4f94e83450a791d6de965c3e8127c1c915208f2b85df4c3a84b2042f0100000000000000c60a9f5f89ea3a56499bcd39bac7e038c25f5b7720d873fdc12b68d2531eb650010000000000000040b77fd8fcabe868dc7f2a08bf14c67e4d433886c3cd3738d1b0b9c649bafc2301000000000000008c43dc50f9ed5bc7be6b4a648957ee5b01a2cbbf967077a6044d4b92f2c715070100000000000000fa81c1b7635c3f695915443a2dfc030e980cae09e592f555edb67436aa11215001000000000000001296762372530d2ccabddcbd204fa90217ce28c9365c5cf4a4eb9f46545b786a0100000000000000fe621d474a018c4e2265c864e994a129614dfb473339453f45a5510587d0174b0100000000000000f2b63387ce5b649f9388fd1be38ee4357b48dc0146e78b91f8f6469a78dc9f580100000000000000b2ba57f89fba50ab178f10f10f2ff79f6061cfec808679868eb7ddd8b08031340100000000000000e694e453023e9989a59e414a8783f9269e933574332c77067fa7ec2b9b6876100100000000000000dc702f22412e64b699d65c66ea2d0857e7b94c0448346f86068e658fc00c5a2c0100000000000000ccb4e6006ac696d5050bc790beff6eaf61a5dbee1a070f66c824b962fe177b6901000000000000009acfd215519f40156749868afc8d56e015759f71cf183fe68382e8c02c75b251010000000000000038f3f4c693034fb614c804ef2854850286df0b1411e5a0c83513ef4c4fa487050100000000000000de5f9f5ad3209502cf429630c2038b8818b6f8ce5685c2730077349802c579250100000000000000649d1a54b0a158350238c017a71aae21e3bb73497187a010d97e1e1b21e43b6401000000000000001cbfaf2b91ee79c6288ad01dd5787070b34d5e1b8253a1765904eaa7d0b93f02010000000000000036a547b4aca95274437f3876bec0447f775eacd01b09d95869390d326a596d450100000000000000a811667da1a12b408e2eddd3fe118403e1f8926b703104fe34193b4fca229d5701000000000000008e83fc9e157adcb687b4b994326f6de340d80075bdbb590eeaa3f29f457ef3560100000000000000b2afe6968bf90de3f8cea025a2b2b0b560b1899fd23343e52c778ab45e1f685f010000000000000026f2af62a2f0d847e3d2cccc93ec7f98c80a7b6d1bcca4cf1c4a6fc7f81775010100000000000000aafb720e50ac6fe69aa177dff62a733a0e98cc0fe7c35e591127479e7e94d5430100000000000000a8f7368dec8f4f30db015c4362e03cd588c6e60f2f4f69912ee4aafb35df38620100000000000000e6767e8c251c74826054421ff499297c13ab6a4e84ce10e0dfae4e21b64aca7301000000000000000481a58bfdafecabbc96bd170a0ec04cc35100f1f928cca3ecc63b3639e47679010000000000000056935ed80a27ac471336a7c5a8b0e73432ddabdf5fe8992390cbae33a020883601000000000000008ec5856a5fd17617c0af76efea16a87d0c5e769eaad39e91c40dac93fb067d5d0100000000000000b0d7d82ba2eca517d6d899525672a1d236f907565785e41ba80296aad19dc57f0100000000000000e4be18b8f5905bc41fe3cba2e5350d405e76036328042ae7edfbb6b6a9b43d5a010000000000000038a69f047c05d50988318a333c2a6bdde4b778592d66328bcf44f1472c1dab500100000000000000b28eace0661acec97215230b9aae3c2be19ef43e9eb90554ab44b51c6180362001000000000000004ed5f55ec45727a57e2d8d6914f6d2acffb17b9515d347ba045067502a0b1402010000000000000036b1aeb61d78c234c0448c0622c570c33ad8fa7b5d7d12102ab323b7985d31690100000000000000a6cfacf0aff2d5c6e8eadf71f397a64f2863e5f0b8793e3068aebd5b3030e13101000000000000007eb2b0b6adbe5a5bad38f46db207f94c896d419661f4ab8f21e302a543df9b1101000000000000004014ed541e698a7a87888c6b5f0c54d74de28c8cd3bd8f1b1f8fd7fdb757cf330100000000000000b032afc9e8d2abc223f23c1d1e1776b3c66a23f5917a7669d69c2eda81b08c3e010000000000000048ce0aba6f1554e139568b4d2358d6cca9bc291d3600787cc3e732291002ca22010000000000000092239fbae2557ff2ea3952c962e478e6ac2a5b3e3cfffb0eb40e8d41860ab0470100000000000000e82715ac0ec2e1f41af952f272f20ef2d2ef826c441c6f33a95522270e57db4b0100000000000000469d81e8b43725a64da6b1ce10eb53eebe1aaebb9703f75ed452e12f45d262730100000000000000285987285ceda1670b1a2fc5c5cf8578a368d63aabfdbbee83ea05db6ae376470100000000000000c4f22a0641190f1bceebea3f8280f22469d6ac0d9b27bcab27d778ac517d2479010000000000000026106dc6fa26823ed60e52e0b1a164dd897be2f617bbf24ddebd9ab34bf6de7701000000000000001c71bcb434190e911175317142b8589619ea3087fb2048a9117607b7b11d11300100000000000000a8527842f1040269688813eb1cf64f525cac5f9219feac35b2d46bcd2df52d100100000000000000a670be090a366ff66d8f7d1eabb7514252222507111e53430bd437a8dbe53a52010000000000000018261ac5151f160bc419a8e44d85fbd4cd8669decacb23c8d7f36f316cbb445e0100000000000000fc53d15453457faadc5540c5853f54324eec395d3647fbf99d5e6e97ef3876760100000000000000544d12f359dbe87200565a9697af85b936a1b5f9d0a363f2ee540ec544aa761e0100000000000000fca464b97dee2e318ad8d4516fd606a5401f5d15467110112a3326ef96ce00760100000000000000864cbd281011a154d93d0320865ad67ae442bf0985f0ec220e2c7db4b095993101000000000000004c696de688ef5d4d5899d1e596a81fde52db76757669bd0051a155fb2335ed0e0100000000000000382fb32d7c8868ce3765e9ccfb462c04071a3d70cab3382c796a9115ab0c310301000000000000008a6dbf87f769167b4eb982f63b946f96a1f223b6a6f2789183fec09581b8e9060100000000000000b027ae418b6c79d9f3a2b05df499d3aaecfb327e6b9d7995a022dc5265ed76180100000000000000eed7e8e8a64dfa89c548a31c1b9fec7af5aef4dbbdb26997b2ddca72d4f8790c0100000000000000a811cc491bb3487d5e604dcf6dca3bf529437162f3b8cfb8514ffab16809ff600100000000000000fe2848018ac215f72f551e58dd2d065d99b788b5a7aa59b9f9fe47a5bdbc046d0100000000000000b6ed5b0c17ca7560c71f1778694741009d3da979309617f0bb992084019e25290100000000000000f853a1534a3af56217661420536dd7bea0db6f6db843d8fead77c308ed7dcc7c010000000000000004b0ff0440c7e131b891a3c13c6f7f0233dbe80fe90dc097f8c5566f2bb49a5f01000000000000005af4895ad43e058a09b4982b8c78021f1ae6cdec9f6633089f32e948ef0d2a11010000000000000028702457fd7ea52bb88284bfcd721493ceae3ea984492a1b82c55efa1b62fa39010000000000000036550a8edfcf14f96e29a7901f5610b57722dbd68b48608572e98468c5bc1f6901000000000000008a51ec3cd1c7e1e5cdc0e3697dd028337ba54e18169cbb241140dbdcc928695c0100000000000000c80832d979a4ba72f7179c346fe660490c292689da81d790baa30a76b598ad5601000000000000006ef86d4533f47ffd133c63b9575c17234309ab6e16f487ae7cd8914169183c66010000000000000056606b6532cdbf27358fd067d61c2a65e4b3e8934c266a857320ff18e5c7654c01000000000000006e8ab85645445eed3828ed583d9a0af03a682fea56d16f833970a3289088e2510100000000000000d096cea7ac5f1bbcaad09ed4723a23fa3b582cc352182a49f8e4511acfa6f87a0100000000000000481ef876bba4865bb88d141606632b3a482c4e5c58c9c30786f6a279eea8a7780100000000000000f403ea18b9e4e9075319b30bf6b6201dd90d012fe4ba28a1c759d0822b9e550901000000000000000690823277fbe96c145c1686519038d301d63bad07d343810506e2cad4b1145701000000000000006c06a116c1a75e2e3b46a7924fe23ca8d58d2a32acac4ca8d0a1e23e3b4c4720010000000000000094d89cb8df2b03c76d41a6521e5803d6f98e204e1839b9ea747dc7e253d35b7f01000000000000009ce314a687a2e8754e1351cda727fdc20e473c08c8bcf5cb70c9a048b571540301000000000000002801cda4aec5f013c3eb504100b1e29e0e65423219d7c6b1b48b0a424a42307c0100000000000000ccb5a9652f3be5d85fcab3d0b8c2eae27519ae2f7befa40c34b89751bbcce40001000000000000005258f48e31bc89f5d53ea6a12eea9698f8e72c6068ac1588100d8632bc674d1e010000000000000094de02a2418c67e938e449c2297944e13cf638e67110299f14cafd5bf2fc60140100000000000000540926fefa2d0424fd451bfca39a01c0e1a3fc811406e127d1dbfdc6cf9e9770010000000000000038c9a0897d9caff03a308d2120bbe892974ae8cb05f1cfe8b97259f0ac2e85290100000000000000a0b7bf06b6c030493f2107c1f2c4154b98b677fcfd461e5817b909f31223a5630100000000000000eab9946bb96a047e9c2fb0e6db8236e46192bcced0c8ea7319142a73cfaf000401000000000000009a53749c83cc06460148d884f1ea5b71897466b237cf16baa45395d78ce48c1a0100000000000000f46eb7a2664580b8655261ad48df75d27404fa23ec47012148dca3c48783bc39010000000000000088fa8bb07ebce99964718c65d0d6f1b091ef2f4d4cdf7b94a22c42c007ecd70601000000000000008a0e2d0af87ffb812f6e6ec229d02056e812cc4f5f5743cc638a7d3f279f0153010000000000000092e5bb9d0906f768dbdde0696b78e493cc78dc1f68789575b24f0b962799b51e01000000000000001ab9d2c814ed7a719ef2aa94dcf4db8aaa0315a59d4b5699e86656a6ee9ac5610100000000000000b63f9ab3a147d76614bfb688751f79fb9a120d40af7ba3bb123c1957b91a411d010000000000000010e37a12fc6ed768d1a2d33c8abc6db675381dfe69c832abb77d9ba2341b3c4a0100000000000000bc62cca37518b73aa22efed6a88147f84af5db7b82ef7671d9bbf03c76d22b4901000000000000000e21a03fbe9885a475c4875f3f912c8703945e99cd2a85f75258fda7b6022b7c0100000000000000206cc2601e4cc1c4d543c1f22eeabb29d72dba4e47630882b2c783e6d3d1935401000000000000002ef372f7d4c71a60f76f65c8ba860ccdf38a85db80963c7f569990ae3865cd470100000000000000068ea8205451f7fdfc6e72059bc58f56cfbd2edcf349f3514de9b00d0c54856801000000000000000e973b21dcbf05732a16fbb925cc44f2f09b236020324c4ff4688614246ca86e0100000000000000ce571a94661c993c3c9309d3ea50f655a55aef1114b548e5309a3f7d506de70b010000000000000042c56bdb09d52942b0fedb07045113a641e2fd64a428b1fa608b5adff9ff4d640100000000000000a0a5985a2d831cc21039cba304cc7da8512cc9098440896fe45ac6dbd8e6b3300100000000000000108c7ed0328d5b09c3f2800da3b8bcc812eda208e3ed636ea1d5a5f312cac56a0100000000000000be8c20cbf28d23f4ee2c82d16d92b7ffd15dbc8e3b64ece63a24ff703f30a07b0100000000000000f29cb4064a1cc3a79da2c9a9f336053cc69d50bcc737257ca2f071c37030510a010000000000000074ee45b1b895aa42f0ea4642cd50e29e43f741f607f25fd5be35ea8cfc9c1c1701000000000000001e23aea69748f8f1d4f9fbe21694942fb42df344e3e314c4a017a4026ac0d31101000000000000003e07b075219fc7ace8dc3bf3a06f5dc12aa9c7e45fe30244d2284bcfb1e6ee1901000000000000003eebdcb51baa53794fa06a4068cec848881ed9b400e1bf1e577d4815c69ba74101000000000000002271d61469f9f1e5a0832af7de453015b89979fd740526080116295f4a4a516d0100000000000000645077cf303943059891df150649d1d828052ea4249bf50ca3b6d29c6ef1984c0100000000000000a0168573a861e2576ab9c5d74d5a5c6e094e6e0261db290363fdb096da94786b010000000000000022376791bf19fefac611324d27bc6acb4b7f7eec713c186adbeda5a1e1b88f340100000000000000aa3463dd8ac73ea72ed500024f5b8bdcca5b20aa9ac557cb7cf980977f120064010000000000000066afec1ea0202d0623f3f92bd2c9e8b78dcbaf4ac7d5fdbe63dd41a79515806a0100000000000000bc8f93a45201992fa9d04355095d03adeb5ff1aea206425eae4f902ffd47fe20010000000000000034caa67978c1a5280b5f58196edcdb5c864b02d0fd40af9c6e6b9716f3fb12680100000000000000ea03f9dc29ae9b7a053c12b6079664592d2cf46a30b43edbb2d2d980223deb110100000000000000b20050395fc81aa60508e362f02c75faebe3e4909c7a23721182ce791bb7011301000000000000007cf1bdd921922cb281bbbeae6fc07218f1d47b73ad3f0f7902e9a7d86d705b080100000000000000526fdfd1d78345a1b2843d392122962cf89a4f157af2a3d0c99607f506175115010000000000000008e80cc5ada5e557a1cea3658402bc83f9892b5c4e112b6e157e6e7d3663c47b0100000000000000a6730d04d45ee4e7e25d3f7b80b4e2ac12a6644a4128127fbe97e97a1d690d69010000000000000068147c36d367eb1a203b303c65ab3d32fe777cabbca8d39e08ffcfd624b3614d0100000000000000b6ad9df8c32a78e9481e75f484fd0b740554276c026736f0dbac0987db08856701000000000000000a6a0f8136fafe5c2e096704e37d12b47a1e46151489a23eb1713b37769fdf780100000000000000281ab8d29fc2bf57650c90e6ab4966f050d4c5c74e94fa659a78bf1dfa71424b0100000000000000d083ff045870d501ac65c3b29384fe542bb53c20308fe740f261caed7ecb04410100000000000000c4687b6d8e527d1ad3be71f2b242bed92eac25b159d9e142e6922ace2dfe5f2101000000000000001437b1c354ee833e93db39ce7b54269c486db9ac4f5e6bce77216a04d7cc376c01000000000000009ea2cb3e6c59685087e59d6d45fdccdd5e6fd4f77fd90b4749f65113e23f086f0100000000000000cc60431feaf7f1bf42d805f0c12a1978ca9b3ec0a21397a71ecfc2bb7d52d20a01000000000000004a7791775365fadbb61f37a0d2f6d298c0c7c3a4c9402821ec909972fd5f8a4c0100000000000000fe3bbb52c1e1b9169ddd63b8f8d14f14d1f291fdac7387deac13e5ea1f8feb6c01000000000000001827754b7465edb9bf4ce981bdd3a33057f9450fc895e39654dbd51c3ab9835a0100000000000000ba099f95644de464c05e2359160bef3e682b8ef3bedc2d5f34fa1a575224645d010000000000000086666d009342994d248819055032a548e2a964da26184293bb9bcb84f5d5d05901000000000000004854cac0c8e7efba2bb24c236cf20212c5a1aeee9e22ea1c97f7b7f61993f81b010000000000000052978f35bc7dc9cd664d2224d164b8de42221e8e6942d66f47a5e9e95cc95d470100000000000000fedb0e6bb7420d16e7112167b894e2da0287b2a170ea43ac038dd416118e156e0100000000000000e0d28dc9623e77eeff6b0aee79793b3a00cf8b1c46fb79c8e6ff8cfeecc4af120100000000000000d0106f6fb9b008052da3223c389525681d9b6e4fdb73a4078f7f1949bfaa350201000000000000001e1f47deab3e4083f7d353b746b719a9f5aaee3ae2cf6b37a4d710f95d489a6101000000000000004a48e0f85fc8b22e74020e1efeed0e275653e8ecdf028c01f13384def95de92a0100000000000000725d8666c3eda2592bf0b16877cfe8e292f61f0456f1d30fd4c29dd05ef0922f010000000000000004601ba22158973d6bed9113f9976c7947daf458f58ae1943ff6f79553e8d4010100000000000000d4a87be02f6839b90794e3880e77ca40a53a7ebdba4a8a5a9c743acf79c7384c0100000000000000caf6489970c76d9f756bb0b914cbd8beca60312b1e210f9d46b6677b03dc86000100000000000000102ed4107066f497e13d3c484a9fa60e506587e19541069dd4555a91d63f27040100000000000000d27da69172c428ddb80272e6fc6ec90985ee281b45f933e5bad65184bc3b5d0201000000000000003afb6b0dac3a05453f125943b8a26269202d297b991e054ca851fa68bb4c08530100000000000000086b88822caebe9d73149400994a2df6cf317debccde56252bd6616cb28ad859010000000000000014a7dcff9114935084580b0b3f39c1260205e63ac607168795f5b0867f28f52601000000000000009e80c458262141e85c50db48c81b519e5eb97d400b66acaa7f47649e5c23b82801000000000000000c3292b5065b7b78a2de5f4fe397fff21df37c0ff7eef94c5fc4397f760e6e46010000000000000012030a66b25d1ddedf761e0875430a266c847b370aa64dc8c106e4b0b997283e01000000000000004616ac86f0d45899eed3f1246dc5744858a694a92b0abd9f10e52dfc9c28674601000000000000009265e7be28a8f56a974027b630bc37703b7ef21b1b1e4253c54d605f4d10da1e010000000000000046b14e55053a02087c957664d32fdcae6ba1c96051239191c63df564d784e1720100000000000000be2a3b6770dcdcda22736d6705a8d075b77544e73311fd0517058867f184ef32010000000000000058efa50da673a8c3b5799e278ae7d32f9eee340947f793f44348ba17e25a885f0100000000000000da5a8d123547810ba496f10294160840c6e067cca57643c9da68265321e80c2c0100000000000000908033d709f4315e38709b4fbcea1e79a9a91b06cd9d31b9d379b7c6232141750100000000000000de97aa69c9dc17083f2323fef768c1066d0c31e61fb1c57452c851f60569cb1e01000000000000009c4d874baeccbb19733cf93f6ffb2f44d9b9f5191ead84f3550c7b767a75061f0100000000000000d0f8b7532498f883c5c76e05a3c414609da9c82c254aa2bac8e8205d2a80682b01000000000000008ea25b46bbf10e124cdd2a34b2134ff31666a0db69fa2fd17794522b3fc6c5390100000000000000924bef00fa94a5c8d29e672c50c68829db4454a85fce54ed3fabd27b454dcf060100000000000000723f8c9d81d0874cd4130cb58587c90ef454174e9d6d9dec11279a553caf00430100000000000000bcc2dbaf82ccaa470212cf2bf8e87f0639bb9fa454c63878a0ad8c06e39a46650100000000000000547c6a159db6eb46da71179d0d15dad5691617fc7f3c6a672864655997035c2d010000000000000040884e6b9876fe866d109aae2a5a6f1a18bfe3655ec9c1fee848ca927344687201000000000000008cc290fd3d49f9ee36aa66775bd92a04b886d1c2648b5573b91eaf420d2d0df20100000000000000040000000000000002", + "babeFinalizedBlockWeight": 3605523, + "finalizedBlockHeader": "0x78835356007a3483eb5f099af463786e062e8513d025f5e8b326f2f05e8d040ed685710377e7b4ebd68adb7bbe2d509bf61eafb18fce581eb6a0411d161ceba9cc5d4c621806d6ca96d5ccabe0ec3cd1f047ee61015eb765fbc4ed735aaac976f243fa76080642414245b5010311000000cc48aa10000000004a79e7001b31b145320daed393d6e6f9a619bab04c27742be4477952fb46fc4c1b17fe2fa71fec279dcfbb9f234bfea251d8f715f76db1a0562bbbec80d43006ada682bb30d431003e91fba8dfb656396159aa4251a779b3f72c22c18bd4f501054241424501013cce6589582512ce47682b3b5365d7474caf6a6d75bfeb0dd96fe9d0b44aea308b1d8ffd8ce1ddc2f08a974382a154dea572ca87d333c99c5703c2ef1c7bcd8a", + "grandpaAuthoritySet": "0xa5043866d53e02db8ff21ae934a03e06375ba5f3588bd444902794dde526fac2cae00100000000000000fff437ff18629bf1490e5c9b3ec6f1515d46bb9b2aeaa6e39e36611f2479b50d01000000000000006719dee0d6e25f2aabec94019e598524b205b514c1582e72fb9f1be3555300a5010000000000000047f940bc985355be7187c709ded2b689b66d69e61e293a507f1d4f90bdbeceee0100000000000000525c0460e98f5cda7d20e67ea1e27b3ca471760559baa73dcf77b2e163b957180100000000000000f98b21ab797ac19b101f8e446865564901dff29b4e0bbc5badcae7ac88dab7d80100000000000000b61e9b13e849779be8f5378a670d61991875d8e091f359384d7be73d02d50693010000000000000070ba6e5985990ba1b1392713236f1b50df750f10f744cc6eb95fa7c5cfbc687601000000000000005081c119ae99cfaacd677ac4eed05ce7d0d3f9af9e1caa58194564bedff73a480100000000000000b54a0bdc05bf5634a385ad79469726bd507dce50ff5e2e5f6132868fe9ced6af010000000000000057ae0c85ebaf333a6ec3251f577cab910cce072f238d1e50046322b83bbc0dd50100000000000000bdae4bc60b03f8fbc14299f0449301ef7f423a4cd15c6f6a35ea6a44fc5bcb0f01000000000000000139b946b46bee4c61be50c986f2a9ef2e76917644e2ecd842c59d61a94ee612010000000000000076aa25ab781816fdfabc9051149c3db958bc09d2e8f0e10a4d91e0df8c79ec9b010000000000000053352e16d2a27fb3525d5d8750d6ad7f46b303a45e434a409ac727d5cb80432b01000000000000008c54298c6f8704498112ecb24f64f7a28ed2289ec573620b0d1e5a9a44f5fa78010000000000000041ef4a31eb7dc1e01f4630604e1908e644d7cdee3f66a60f98d6d59605326f8b0100000000000000c4ab2451500e321f187140d3aeed09d5cdf67f09d9997b966c86dd74714233db010000000000000021acf715d75065242920f902a3490f2f9f3dbf5bae57a4a6fbc8ed3f805eb8620100000000000000049cb09a86d544249f9e11cf6c348bc0561600343ebee89d1c90bbef3d13e5170100000000000000d04d64a07f144638f20f081de122b88fed0cc8bda57e4810e7afb38036dd8bbf0100000000000000f26945a8a64032a1defa76e720a99649125b55751b6088205e7acab901de670b0100000000000000684768723f0efc2001562c3b2156b987601ae9431f8aaa6f4199649cba487aea01000000000000005ee4dbc4f6c4f07171eda6db4f331180ad4434b34f809071e958910df3252c8c01000000000000009b94bc45bf79bb33f70430c82880456cd7bd5fb3ea131c1b26d493d01c5fe7100100000000000000d7e8ce7ff46c836473acb0c3016feab586b5c4a6b529f7cedef01c6727dbbcf601000000000000006f4855725ebb9eced957bae43ffa7d30657ce7d06b251ce20e2218bcf929e4050100000000000000f2f0f84855c6bce35c42d537fb4022662272203cc4985767ad4ef8ef1bbb716501000000000000008376e5e1a7b6eac21e3e9f9e133f89ed0053b5559376a97e58896653725c502d0100000000000000ff0bf39c82ed573d48585448b0fc19ba3f6203806cb6b4a230848892c097a26f01000000000000009c27510363c46fb84c22765901302fa26af266da5a22099368fce05562ce97eb01000000000000003478e6a5b64e3aaaa6795e6536a12728a20af7a8d44c75f5e981c6d2aee4517701000000000000003b252801bf8a2f4797699a0d95e8fad8c8fb42cf6f6a33f4555bde1c7fefd4490100000000000000c1c1ff5f66fefb5c0849e3b2333411d1f7e9dd4888600e334e7a33623f15fa360100000000000000fe240e80ff8a48a77947b394979cf361017cd906ddaab637d72cf72e729d79bf010000000000000006854c73f5703242d31d2576ac2297c93f0b5dc16ade0097c59d5dc0faa43c5501000000000000004e8f0524e30ac39910b99d0c465e945580c48070ea75214f7c01a920b1a66e4901000000000000008aabd4f6d7ecec7a749c83fc7be33f3b4818cca6f93a4927b4964900df9454e50100000000000000b9186b95c90d2d00a31e7c68066bd37d73408271762604e3608e2f2c983f83090100000000000000f5260c9ada18534d79be08836484429e686985c8241e113307792aa1255b1cb10100000000000000e730007e26ea493e96a65b30d278e92ef85444e61fee3606729a5e699b74f1100100000000000000d4d8cfaa23b3a1a89a7f6a90cdbfdea15c87ad2ca4ae77deb3389406ad3feffe01000000000000002db20e745d850245733e6f6aa93ea9a176044e904160e59995846aac21f1ff610100000000000000dc1427d14e83926d22f6be25d1bd39cbc82a194f5e9373ecae644f156ae9c62e01000000000000005cc3bf681735b048c6d32066de94abae0515d8f401583bf9bb103b4e07ec6e700100000000000000beab86851a829fb4f25d1c1a5d92b4cd97718fd0f2f9ef345b0d3cab98a304aa01000000000000000339088379600f5bd507277eb894aba34d2a8f27ce1964f41e60ef2a4142dc6e010000000000000003d105a30087d96b5f0684f6ded76f826b01dab61e4136e1d851a24f0088b5ed010000000000000020d4e595c50bb9558dad9be6a8784492bbbfc754b9c5fae17edf4f8a84e8b47101000000000000006ba031ff146af5199eeb335a4a9c2fd487685a489e1a154ba1d012e965fdd5ba0100000000000000608f61824d3ae16d443cd0fec15c18590c890d4105e9402cad8743fb423e52b40100000000000000fe95aa161a01b3473ed9dc7f4e2219528d8be86530bcfa7095086ed61e3d7a0301000000000000000ccee96768f9b1d29d5bd9e63afd2be78a90cc89d19653ff1910cb36000b48530100000000000000818a546c630b881c2161588866965649678cda0f4110cccc3533d0f20e5e41200100000000000000088f8736e1cf2ea3d102f0a96ccf51222b8aa1f93d8e42947892f4395cb5477c0100000000000000c3ff25a1743a9df92af4ccd9a7aed5cbc90f64fd538c3df0a9539128f596526701000000000000004e3fb8c16ad624c1852777456805e5352d0221269de66949c95da4076206b35a01000000000000007ad55381f9de00220678c95a19489640fc61331e2a40d927e3d833555575c6fc0100000000000000cb92ffeace78dbafe6fbf275741b4b38657fb81590712aa0bca7877931f6ad39010000000000000074a8906dd2888c9e7edea13ba3c42ad4d833f4a5de43d5ce0d9b12c654ab2e8701000000000000005cd0c7b21d4834c5a41a80f7d421c7d0297e42eb409a524d33aa7557df13adaa01000000000000007ac1f611f90df5fb222924b2c6683062db933d6083922c4a17ce29f21298a768010000000000000007727680e6caac998c03e3702c7f84e558b592dd76ab2a49cdd3dae16e7e853f0100000000000000e78c36a9d8b145c42c879754a79dde433fa2496c55d6d9f00ae577c6b1ff4dfe0100000000000000c6b03ba3484a8eb6518858d525b5a64f5b9db650bcc7c0df788ade370714d222010000000000000059bba625d971d505a9c7d7c2f3ad69203e69e3e5e1fc1e4905fae7703fa19e030100000000000000b79c9e77b101899e5e0b01fb61edb48a2a28c0dc19e6496ece31eef4696674fa0100000000000000ba95f5d0e987305bb794dfeae69d7dd6a7987aa66cd7c9d42aca15e9160ec6a1010000000000000057d2c2934f6896f927b91431398ee0ee820f35d13959ffdb77961c86893c7fea0100000000000000a837eb18e0e629cb4200341ded7e4a28c01ba1384312805f7ba4c788a3636361010000000000000079c7f1a51767cb557331a7ef9d93b1879ae170f5c5e367ec46dc0bd59183109d010000000000000054efa280ecec9c8ce569b293e92733e2fd4a884a551241d92b042be850cca5b9010000000000000079b7935f0302c2cde0ac307993bb5aa917b21ca72116a33d6fb29c9218d23371010000000000000016278af083f6d261762f8a97b6a09ff83e2f5927ce26c2e48f3c7e771dc7e69501000000000000006a4dd2a5375c3ed37eca0a5ecda6ad6d7d1dc9818a588129c9529b41706c28b50100000000000000c49e3cd2c701bb845963c2870dcca12ed070c3f67ffc20144327a93aa6e896ec01000000000000008041ec7547fadc33aa19a785dbd1a7058b0147f2d9736b9dc4dbc6ce454bd7ef0100000000000000b659572f1985264ebbade17666a860f8fba53577db37ab74d510f8250dcf591d01000000000000002dad5b2212ee688f2eeb9ca1fb6a90574f006dc1c6680ac3a8523363a248940b0100000000000000b7c13f1239888cda5c8e6ac9ea10675df17633368906e66a487f91ddd3268ca60100000000000000b9404a5fb9f1723fc9fd4c5535dd9ef1d67c5237d9d322854697e9e245064e330100000000000000a7c97a8b886fb36c1cd26977af2dabcabc59e565fb2ac4662ea3e825ba05eaf701000000000000008cc5497465564e76909d43a2baeb935c9c3ecba972164f0817940b51b83f95070100000000000000f3b1c0e43606bd49bc84e403db685b577e898b5f7c5db9052bdc3dacf38dc7ad0100000000000000596004e838b7d90408d46de62b01e13e631575f348bc59f926286aae4c88702a01000000000000003a511828c0cdc0fd257387843fdbf6f19d5ca1ef1c29ec7e971fc9f1195eb60c01000000000000001bd2dc1433466b9f53f6f564006c366f6f5a77494b4c61c0fa10a746228c7d9a0100000000000000ee5605c1a9ed9484a70b8a591339830f24530eefc4599a7c6188a78896908e2c010000000000000058a618057cf738d5fe0ecd46959bc90fc35e75abfabdad47466882af2328f4510100000000000000d1c146d2429a5a827660008721c7a880e71f44feaa3dc75524c1a9281bac48cd0100000000000000242722dcba2babf14ccfc0617b1d63f0c62bf4fdd8d589192bfa8f83b0cbc25a01000000000000005f7c962cf032d27424ec830bc53534062389bb181aec9299aecc802dd71c144101000000000000002bb7b11dfe79a12110b0370510ef20d40ba8a563f517310f8bf37cf7f0403de4010000000000000040533a786cd0be9618126633512666b1b1b9ab3b436fa653c93e2f65da9c196b010000000000000096d41ceafc16873fda98efcf8cff835c433af51a2cdaa39c0ce71014151eb91e01000000000000006a5f902cdeda2c2161d16bd21d586720c08c0bbb7b463d9c59147338d26a8a96010000000000000031149a16ef2ddd8944e60703a88d8822649f7e18e3d5368c8b730bbe2b5ed6b8010000000000000078ffabbea4ce0d6c8208eacda97bd6aa8b91fe5fd1226bbb08c63c12dfd416aa0100000000000000bba0b1c17968bfe96655ae74c78552858406e7e831477dd6061a036fb58103c00100000000000000ab46e1e7337eb6fb53e1a022dbb648b5d92761b06322a7173b73c8020d3c4f62010000000000000056682332630f5dd42f160f1e3475d1881b2adab83023216892f538efa1e0e66f0100000000000000c7d9cab0fb88dccd0cf4abbf5df9d7f36a3de439c5070c599d397e74133bdfed0100000000000000866fe4ae134938ccf4c5caf01358881c75cfde473b0bb8a2623cc231db2ea3b901000000000000005cecf03ce3d4f89afc378058886f46a745f1672efea7f0a01160cf2df98bade00100000000000000136f0f103b294ecc41b3659fd19b251975ceb3f0b85379393303ee1462dcc6370100000000000000fc555c014d927fe7838e840609916b9af5d93892ce6f394398858286802b8c6101000000000000007e9a8b0613bf51b175b7c446f29daede6bead3f6d1269c216ebaaf770082420301000000000000008c3dbd5a1b928cb51e918452191e5328b0f6e8de0259517831a90b02dba3e6110100000000000000aa6fd06015b8309ea9103f4b0e29bfa7e21ab5bb1431c3a76433f591c739f8380100000000000000fbe806f96dcc137dcaea26125661f35d36aba1e2b2d7c89cf6a536c1a721c3a00100000000000000a892342c56149812a43e98c82b6a3dfee7eff384d9b6d832002ea63838f6490001000000000000005cd92a7f0b1a7ded1de21ee73439f8851622b8d3e4664f68db20269cf0ede9ef010000000000000023f07bcb8dade90cefd08732183d5fe32b89ad8a4f84987b9e4e7e767c25875601000000000000006fd2f5030da02a05fd978e836967d2329d916c21d4081d6b9057341535afee4101000000000000004532b59911aec8842fd910a35fad7c6210b3c1ac73c7c9799963c635e2b562880100000000000000be6b59cb464fadec4e0b22a9f12857ba5cf7a14c4f9551439d36305d582dd7fb010000000000000056cd1acff4de0c0d403c9f34bcafd74cb9e50e47b0b2ffda16f3db9a5fa12d480100000000000000acc5d703d7819d7993784e6ce107cd4c5625954d3baab0bcc07afe7d8c473a220100000000000000300c6f7d60252ecda817a4161b72e77445ef0f95874503ed01533a78a917411a01000000000000004ff4b94f982f0369db2cbfecc73ca3d9a87ee18fb9ca5f5b3bbe4d4256833d6a01000000000000004b98c985398b5d64b7c1cc430cae9fe4a7bb24e6051db62555a83c966266070401000000000000006ade09347d6072d154bdf0b13d0814ce9bf2a3b163c7092d71f0ed5cdcc9e1c90100000000000000a36ea7f37e51f64e364faf6d3f59fbf0a4a638e1b1811484df7423b68fee42be01000000000000008cfea50157362012d46ebbd35d758d9e7e583192a19ccd9fa44e8e566a2f5f610100000000000000d0b4aada93fb3d0b358e8d59f8914f5987acbc6f5b4f3e12a1ed8d962eded82701000000000000004f950be5bf61958a0ae6e6a036b85b33ba838de8bd5508b558cbe2602d341168010000000000000082e6b6bf1f275c59fbde0dad91393ae690d5e644d11d23898a9ccfdda025920a01000000000000006f7a1a4f9d8c054907f3b6b946a59525199dbcffe9fd3ba89612a5d4b548bede0100000000000000664321f9b5f8f1154b1f6ecf936629232bca97b4e6cb7b15b18f6788df57acf20100000000000000817c2256c3f90205a1618aca11b5cda153d906f19dbb071168b5d3eb2dcdf6c3010000000000000067baa27826f448c2761c7d56beeccb4be9a09b9da7c99ced171e47b5b40fd66701000000000000005b379072ec1f3f70b4650979a47b24f9b080c03450f7e9587d92cb599fcf4d6b010000000000000018b45f8c44b86e28967b6a1d16b7ceef81ba4dab940af7f431e2c362779bf8f601000000000000008934b9a6c38dd420aefa1e115c839fad7a71147a6efc77ab593485c3b07576ac010000000000000042767549be650b14b6006f20f646a7b03548181bdd1b3f70fee478f105d0c55c0100000000000000d6dfcd2fd4743915bd90a97b149d985bab1371d416ea1c94878f425b2a312a9c0100000000000000d3b3d9703a265a51a137b9de348587c645a168981ef3e01c9dc482856751b8ef0100000000000000fc787e0cc80b880cec43b8186eabcaf905c6df87582986fe724884d8f50addfa0100000000000000c0444bc7cff2374b76ba49e5ce25b632b0db77f08f6c40799077ce3f5b035f3f010000000000000096954a8ab821a253ef8b1f37f77568a7ef10e3ae1efb6e43d0308ae78888c5270100000000000000a2ee8d9c22eba97998d63854409d99c87b21d079f5c888d863a81d41d6abf0110100000000000000c2344c6fb787621295335b6b5acbab9531199901492d41e13a64dfb2927f83be010000000000000069d5a9da53c043b2852a9ab2712bf10e65c375234a1b6ce75b2e73a3b38b4d0501000000000000009f8d5dad0f5f1acd843c69570a7e34d3718903ee9cdd9cde4df53c0bbca5d00601000000000000001d704a1e9e8ceb87d7ebf583e96a6318ce17bf25ffdedbe57a4fb200f9c8f2060100000000000000155763a153e0c02b2eef1d8a9cd8a50a9eaac9d3af7ad1e559b1e2320b521e1c010000000000000010dedb3ee7bb127bd7c1819086e799b37693fcb8931f5b454fe98bfd92a9124a01000000000000006f24952b93da464bd561b3f9b814d3884e88cf950a204205027989a1259c0bd001000000000000007cf464ab5e56ab05395c73c625ce4fb0b89c4cd02316f290ddf75fc7b189eb6d01000000000000003773b05d2e2660498c8d407a1d6223423c26aa08b9b3656af94d78b861fba22f01000000000000003ca72e96f3893cd5250ff6ba60a9cdfa049945a3740ad6338398d70a1355e06f0100000000000000500a9e1ea37636c24ebf4e32668897dae936eef42b6da49027f606d4f24a7e960100000000000000ed171997fcc2549c08a39a0367b723c68434e08b7c104320f410a6da9a6d822a010000000000000039712f967c4e06d284d6da4735cf2823c1f770674b668f7bc896071c3fd41eda0100000000000000d42a22861f9f410c2f0733d0aba4ce6ba6cfa9c69ad5b6c6502a2b99ae8c0b49010000000000000095fcf1464d41feaa1f7659756d5278e7a42dac7951ed211f6caeb3e75285c75b01000000000000004df6e4d7da2c11ddb9153c714699f9ab625bbcd5e8e38f1cdeee567dc04abc610100000000000000f2ecf2265889c11a724e4fdb0e9f0fd9905b776989014222b047ff9de5fe401401000000000000004c3b4b0a3acf902acec7f5d868f77d78b17fa4cfc5f785d393c9f3d15e0488050100000000000000b8cf76a8082d518016ea5588be57b64e156ed23b0f72248975522c23d15ef161010000000000000069bfcb1c0cae6c61b881995aaee8fb2ec30183eb4545f17df47dce0c08a0ac660100000000000000a3d9e6ea3bf5bbaeb654fa0667fa89d6333e1bda95488c5e0cf70fc3a6f5f35401000000000000002565e04c6e0b665fac87f8238bee74837f8f621ed63409f3838d263603400a980100000000000000c2e6a39d423f82b034e5370932f02653ee45254ced3ec2094640508e3d04d91b0100000000000000f25a93ddbbd03cf6db28c430de1bc7c0cc4ab2912f9df692da294a3d97032ec301000000000000002a38a4dcdffc571d547ee3e59121fdd378335df7c65877f983f0957cdc982413010000000000000013bb7d0d3ad02c62ffe9dd420451792fe18502818635ca189cdfb27cee4e0ae701000000000000004d7c6836bf41d01d5b58d5c8748b9bc7c0f1a4f101e19a9e8aa17c970a92604e01000000000000003a76a7eebe9edea2fcfb70ed044111a1e8f8aa85ee30efe364586845cf28c478010000000000000053db8eab8282ff36ab195de04f694c726085d18722e02ad3713c7e0a64353d00010000000000000081c5c3bebb947d1716d5f6f325afdc71c953c23fd85a716dc082790bbb8d19150100000000000000121e86ff9fde3cc3d2ae12c7346e007c7e025dc2dbb9474494659d76903fdf4f010000000000000007509cdb3f25ea59dc90860670b6ca58c678f099bd4d7221f4bc2a2e2a52b9e301000000000000007af0706d921a331b5c1f957a8d1decf15aa0e3377a80d72107693afd8614ef8f0100000000000000c172464fd94ed33d095961d4bc76be9d4ebd3378dd7f5e738996866da792320e0100000000000000f5e2c973d4ccbdd36d8ed4e3dae75d3b50002cc1c74eb0a1fe29ef1ef8e3f0cc0100000000000000f56f5b3de4f46bcde88569888783fd60646806795807edb1e04ec3dff85ff3e10100000000000000a3dbfbf4eba67c252cf10f45008eff4581f97a5c4f377260de7538aac5a422cb01000000000000008b35aa0d212e4032ede352d5426696c260c9ecffa632a2e14e6a6629a6c9f637010000000000000072341ca1eb3a0fd4e790318b51ace114315573d5355c9d5336e39382ba0642560100000000000000b14911cb101f45b88c437a36bd82a5f8641b1c55052060ea46ea2baea570e8bf0100000000000000b66e24ea84d5e02a7b2b58e20bbf17a0f2a19c4654bf8b07669ba3b9fc4a468101000000000000009d31c78ebe9664e2bd8ba41cddcd9c5b9fb0cc6f8be0a2e5b91f6bcf66a5c7530100000000000000290be52ae5259f3e8bd0cdf454004607867a97c1db86d0c9ff16c8c83625bc830100000000000000c91199db47b7591bf1a928534cdbd3e5979a0d09d6a464f2a9607ec444bd8a9701000000000000004c43a374e6b3e6f7d6c5a6b8518ae0d0d232a1c46d63af8fbc800045a14cbe93010000000000000045983f6d17109e1957bb37362f40a1eb0c8d5259091ee9f8a1693dd821e926eb0100000000000000b9554a4207dfd5c094ae11a6b261bbec2054e3e6bb7e80776b1aa96e24bbbb69010000000000000022edc626e6c76166af032395ade8b874ac872074c72e3e6a70c8f668993d19e8010000000000000081738498a35450b3e36b0a8af266f887bbc3205c00aa46b04fab7f47bc0dc7750100000000000000194d95608f8340cab24e8bb302f1e4b02803ebe8f750888aa5da5508019f5f260100000000000000aab24caa6a8d6a66eac491708363c62c2087540b364273835796a54647a7e6fa0100000000000000ac0ef45b1c0f242a4aeb0ef03a9c0d9e3ae2a4bee8cb4c35f0293bac4331e76501000000000000001887f7937a8ca4ec67ceaedebfad3d307b10f416219de1ed4f8646409eab730a0100000000000000f567fbf0ac2c23bfbe654255aed088d1b78c6fcb63a331b394405c15868340cc0100000000000000a3392683550322454a4b5745afbe051746c4e34170ab2af0d1ce40307c7b7f9a01000000000000002c203d61f409a43e44773a1e7024ebb67b45b489e675ef384334e073bb935ad201000000000000008b933a5a22b04aa2c830429dfd61532ad2e30be1c0fb5a2d0c235de403f30abd0100000000000000e8e69f08c3b5aff03e910e1fc0de0ec6e5846f9b7859946f6f72cf967fc154160100000000000000fc2ff0598fd334e425949d552cd31b59e87365b05d6151aa2e8e982e44f296090100000000000000ee40b85aa515fdbe6e559f815edc7ec1e321e0d152dd54258382ba31b54e447a01000000000000001267b8cba49007ec111d8d037e52e3e32c7ad6c2f41d6b45e90b8402a24005d30100000000000000c3e904b307c280271b2a2bca82cefc7e14d75f776e08ffe58fc4f7fa3d1d0a6101000000000000008dc1439b28d488419535c2fea9c821023f7bce423fa02d9f42e60c07c3d6ab560100000000000000c3150e4ca47e7bc6486f198bf0a742a18ab0871bb1efa34e82c4ce81f279266701000000000000002e8f05a1e5ba68d6e4b93c289e885f630cf27f720181060c437869ab9e83939101000000000000007a92827270cfa82f16145a44f9bdd9ff5038ef1b665dd520a2e61db9749094960100000000000000ebb1834a568ea7653bc66f394937a0aa4f2f617118d2161e2c11c0d7d2febb9d01000000000000002ea29e0897dea1ebd35d08aaf170ffbcef9b1add7a80aa3afdd9161fdd4329e00100000000000000d49bb29ccd716262579a5a448c377aa16ff969d5b2c282a43de87abaf4174e930100000000000000e5f305cd6d930d41209036f066a86d3724aad2f388d354ac4979cc763c220a5601000000000000002605f256953a6cd468cb45aa10509abd14d606166578147b8f4d2c70e3c5a4d3010000000000000098a6defcfeb3dfca36ec46eb373734627a2c395cdd2d886046a11788ed6467af010000000000000035db4f9ab121f213b695b982f50c47ac04a14c54214e831ed1bbef7b9542310c0100000000000000496826b538d97906e14d417b48598d7d591a483ab5f4c6786cd0b96239c2f4cf0100000000000000ef27d1d5573e6419ffcc7c4372668105118256b810ab2e2dbb5e7d8280ee94250100000000000000ed3f97f83ee7799c4aeba9f40bd18134c862c1a30875fc1e038cd27bae3a739a0100000000000000348e8bacc2d40191a6a00e137c745a422ff8fb03148d2ff9cad75efbb7a670140100000000000000cafe2356af019d8b5f39c949b3dee71dd5356eb2655d819f485d0244e55b9fcd01000000000000006a5dcdf2c3598c00d31a010dece5bf744f203856712531b07a31babcf06d09e30100000000000000d03903d0b6fb3ea0891ceeb3a84afdd6979f453d70ee1531168e418d0a8869720100000000000000638bc7ae8bc6ff7e9944c1b108ec4105b61393dc867da3b4ab6c546eb248263c0100000000000000e18f9d4831f99a874b84355d8404b084c06793b62e78cd05e479e7e399dc686901000000000000000938374801c6b36a9164ffdbec02bd2d54b7f927a850f46136126726774166eb01000000000000002088d13e2c7afbe1ab78d935d1d8e02eddb71276a0c9bbf5488188371200f5fe0100000000000000bff74b6ff5ccdce9a659408871d486511938422a6e550fe0669ccd739f801081010000000000000082019acc07b285d7edea9f72e3d5285312e994beb056e6faf58492841a80d282010000000000000004eed32b0d6be0b60d2e33281f623471f3a65de597d2de13c0d8f887ea723aab0100000000000000bc969803075efefd39758affc268d35239b19b63234bce1a8681d3fe5f4540570100000000000000e01d6eda8094e949bfbb05c819b509a12eb662a414b822f841d9555d58e1ce7601000000000000004d12dbcf20a79391d84bee6cb79bf8bab502241e46e52d45c2ea66e3ba5e9a5f010000000000000044a98b8e6c68cbd67e08808496605cc3ac081ae433398676543bde1720048e490100000000000000c3576342cbf99792896ee5329b04ff2eee2fc2bb6d53c5c03d52c8957ee793fb01000000000000005f4e596a0de5073157b4f8a4609e716109a53df7a5bc2a0c24edae406bebcb240100000000000000de186294778cc927cb2a24ade9ad165956f3586979f1ac5f3b4a16edd2674339010000000000000043a9a2915f377cd4943f602be38c3bd6ef39e91562c09f18fb672884b4bf8eab01000000000000001a608965f3df6f3b63f91616d5c7878c3decad01ea6b3b286be37c62e30118b5010000000000000059dadf17dc0f84c1c334e6a815a04bdfcd0988a3f3bcb713c66ae29e17276cc601000000000000008d5cb94ebe135f3e9fb84ed39aa213a14c57b98f19d2cf35f2cc450b44e3792f0100000000000000a770d6b7bb38159344a04fbf56b79c21e7cc58cfa02cf97450be8a67c12955b10100000000000000297dc7cf28b3d40a42c5e8faac876bf7227c670e6e031dd0e0537f4fb70e6fbe01000000000000000909c1eff97923f6bd47e6ec8b5dc163b32d5b675a3b13138d3599e5cc77ab9f0100000000000000f7bdbb5c598784ba157940b08b5c5aa967d0f3faf60da28b915650eb39afe47c0100000000000000677358fc648638cbd854d2a009dd39b8508dd3047d0c5f13bb403a64d053ad030100000000000000f4c1dbe557387df6714021a934e2227b372de5b5e0979d57f4e6ab33c4859e8c010000000000000073dce1727ec50c50366378cd389246e19543d900d7e9dab8e323d04cf5b202a701000000000000002ada479e1fde7211de15900ed29035f6f07506cdbadc4c232aab96d62006b9de0100000000000000ee1a56541083b083f1a13b5f8aa4042a098de2cec4c43f3250baaba8f03a52ea0100000000000000e2cc4424464983ada824bbef5aaa8995e80ef1017c15ef3b13902599841637ba01000000000000005246164c02e9e6bfb7a2dbf7ba8a5440a189f8048373678f5b1085f217464c0501000000000000001889f1b031fa7d64c4b480a17cd2941be2c02681bca397c93607091f37bf5ee10100000000000000b884577e30ee6428215afe3b9bd2d7b5e50f724d74a8e11defc1b52ce411b3850100000000000000dd2845c96358e8dbf0826903b8451d6d374d39b476eed17552d190ed684680cf0100000000000000fd734da3c98d7d56f8b9cc92f389350f3b6de2fb5917d338fee9fd961978e2a301000000000000004251f97b79a45e8acb5f73c11f5fe4966cc998fe4703e63342a34c3b8a345fbb010000000000000084845f99ad8fe89b7aa136c30b71b791015e8801b1d42cbf9841a0b90e723aad01000000000000008c258b4ca16dfb8e5afde4cf40fecf115307798117b4860475511b3b5d5615840100000000000000ea8c8bec277832ff4f31396f76d6117026cf73407bce46de9ccfd17c686ca1170100000000000000a345327d74e78288985f9b2bb655885221105b0c76c4db2f021d60cb74e2183c01000000000000000e7bc96895730726225e47e31c742fd44d3936f31ecd32658c694fc11df252240100000000000000a3316f9e3af8d72aad03079e644c89cf5b97b302b506ac296a4da6aeded2c8ce010000000000000017dd31b9a0e4e050b82550ffe7920c3f53392afb5f6e546114921d5a4a2b6fce010000000000000055762fe2197a58ce7c5f23f3a3fd6f16f1d8845d6a0b13459491a65977553bdf0100000000000000ab99dbd3e4ef435e0920f0ee4ec2297d665ba8d5bf93d024e5c34ed738b71b8f0100000000000000c82cb99a034e1865554243136d8462e6b2e840af79a92b965d7883619d40cb2001000000000000003f6aeb3ed0d67d71ee11a1c2e1ed66da77abd8cc8c0f4d995d64fe4ec873684701000000000000006375ae0c1bf2b0388e16971715fd68c31ed179f38947531c165f0da2c3fe7667010000000000000012aa455c35356255f9ba286193962f3bc23f7fff565c1995ac21015bd946fe6e01000000000000004a46371fa537ccb9ad995cd03c69517dfd310fd4af9d8a95c7976cf8eb6c37fc010000000000000025196076d22b8093c7a53a1be1f9ba73d404c73dde8fd8c49465990eb7d7707a010000000000000018566ab47d72a4a296fe9712acf62d6d135328372e4a3ef7b99816d6b4beb6840100000000000000a2a4f4e18a49ae5fa0170e13427a58e53779a64bdbf817183420f9abdc0cd4090100000000000000d7a0c586d45638b0c2b335420a57c73b2acbe1a8038a25c800a030ffa1e62fbf01000000000000004485615186ae8ad33aff337594a7f8325d3a50201ee04320fb1dd2eab9643d1601000000000000002b07c366c1ed899a2ac9722b76e092828714a8177368e51ca05ec05c565866b30100000000000000e81206b483fdcf1fe42145f27d1efb8178a57ee24b196285374037da2a53b3230100000000000000a0586d138691972dad187e747b31698e301c3e1d58d5ff6be8a06d4ec5d6b855010000000000000027a748182c49d7c4ec091c9589da5c9c35fa99ac8ffa4d613129dd4d08e9f11201000000000000002773bf65269603924e514b545eb69d988b5f6b5d94310f2eac5fe549cadad07c0100000000000000ff568b8e0dbe74604c6d04b5de6f2df03b343bea074c4495c6a10e511ba473d901000000000000009337ca812d686250385c635198917e85833d7a9b0ab4c537246fb069d09f401d01000000000000003a4bfd825ccd308def4a61bac80c579db42b02ea5f1a0768656a326e83a0dd880100000000000000db106e27c5b78f1a0d19e0abb47b4666c54906c5539c8596b43d36dc885e927a0100000000000000b5e0d0ae74b0ac76c0195fecca9660a241920ba97cdc5a247c7e941ee1f5407c01000000000000001b47bfdc6dc74483d9f8b2b6317c4c1a38b781bdcb8e054ba268fe470a2617a00100000000000000f33b53556f28f27d250585317cd57a18f37c5d5f2b3c1bd00a0c91ea54f1636f0100000000000000c629791ed8a776d1ec9a20659c90c0aa152ecf281d3180b6fbd15e3aad9eece80100000000000000e3d0f7b2d2a791eb30b29f912ea13f9586c8d2cbcd600ddd87b1e23481f2559e01000000000000003ee2346e1195969237202d47b843937c1038c34c67dca5a3fcd1127b9e8aa014010000000000000080629b67e7b2d6f57e9da3cb29cc8463a65d125039628124784f944b94c29e880100000000000000eb644b1724854d4d8b22dce0e1bcb890f6643a3a072bf9f8c8add4e47fac659b01000000000000002c3ce4d7102f4236e0df2e8f5797f6dc3d2e6f0e57d373c9a4b89b21d4d228680100000000000000fc678679f11bc904720421273689e6826acb42b21e2c4c5c1d7bf532d8966841010000000000000030afa9ef79458f844a27a3881655b6eafb90b3912737f1bcddb95e78eb098c1d0100000000000000988049da395a4bc05a5c5967e3e492c95006f08f7c6176a4686889717a42e2c80100000000000000c222ba3fffec09b85f1992db2dcaeaa48205903219789369855e347fd188144b010000000000000012c277c98d0593ec3d0f9d01e8ce08f67813197b67fe96d2be7c5ba6481515df01000000000000002f0500000000000000017561dc0000bd1400000000000000002904050001000000000000002a0d050002000000000000002f16050003000000000000008e1f05000400000000000000ee28050005000000000000004d32050006000000000000009d3b05000700000000000000fd44050008000000000000005c4e05000900000000000000b75705000a00000000000000176105000b00000000000000766a05000c00000000000000d67305000d00000000000000357d05000e00000000000000958605000f00000000000000f58f0500100000000000000055990500110000000000000095a205001200000000000000d8ab050013000000000000000db50500140000000000000024da05001500000000000000aaec05001600000000000000f4f5050017000000000000003bff050018000000000000008b0806001900000000000000992406001a00000000000000f92d06001b000000000000000d4a06001c00000000000000685306001d00000000000000b65c06001e00000000000000f76506001f00000000000000308b060020000000000000007b940600210000000000000025a70600220000000000000033c3060023000000000000007fcc06002400000000000000c3d50600250000000000000011df060026000000000000005ae806002700000000000000a0f106002800000000000000410407002900000000000000880d07002a000000000000001b3c07002b00000000000000764507002c00000000000000357407002d00000000000000239907002e000000000000006fa207002f00000000000000c3ab070030000000000000006abe07003100000000000000bdc7070032000000000000000fd107003300000000000000b2e3070034000000000000000aed07003500000000000000971b080036000000000000009d24080037000000000000009c4008003800000000000000255308003900000000000000735c08003a000000000000000c6f08003b00000000000000048b08003c00000000000000589408003d00000000000000d3c208003e00000000000000e4de08003f000000000000003fe808004000000000000000f7fa08004100000000000000aa0d09004200000000000000153309004300000000000000fc6a090044000000000000003e74090045000000000000009a7d0900460000000000000000a30900470000000000000014db0900480000000000000020130a004900000000000000791c0a004a00000000000000364b0a004b0000000000000043830a004c00000000000000e5950a004d0000000000000045bb0a004e0000000000000059f30a004f000000000000000e060b005000000000000000812b0b005100000000000000dc340b005200000000000000ef500b005300000000000000a3630b005400000000000000b69b0b005500000000000000c7d30b005600000000000000dd0b0c005700000000000000f3430c005800000000000000087c0c00590000000000000052b30c005a0000000000000060eb0c005b00000000000000baf40c005c0000000000000072230d005d00000000000000805b0d005e000000000000007e930d005f000000000000007ccb0d00600000000000000076030e006100000000000000793b0e00620000000000000088730e00630000000000000092ab0e00640000000000000083e30e006500000000000000731b0f00660000000000000079530f006700000000000000748b0f0068000000000000001fc30f006900000000000000d0fa0f006a00000000000000633210006b00000000000000826a10006c0000000000000028a210006d0000000000000005b310006e0000000000000055d810006f000000000000004810110070000000000000006548110071000000000000008e8011007200000000000000bfb811007300000000000000bbf011007400000000000000e828120075000000000000001561120076000000000000003b991200770000000000000058d112007800000000000000770913007900000000000000944113007a00000000000000c07913007b00000000000000e7b113007c000000000000000cea13007d0000000000000067f313007e00000000000000d31814007f000000000000002e22140080000000000000008c2b14008100000000000000545a14008200000000000000ad63140083000000000000000e89140084000000000000006892140085000000000000008dca14008600000000000000b00215008700000000000000d03a15008800000000000000f3721500890000000000000015ab15008a000000000000003be315008b000000000000005d1b16008c00000000000000855316008d00000000000000b18b16008e00000000000000d3c316008f00000000000000e9fb16009000000000000000073417009100000000000000bf4617009200000000000000286c1700930000000000000029a41700940000000000000041dc17009500000000000000591418009600000000000000bf3918009700000000000000704c18009800000000000000948418009900000000000000f28d18009a00000000000000bcbc18009b00000000000000e4f418009c000000000000000b2d19009d000000000000002c6519009e00000000000000896e19009f00000000000000519d1900a00000000000000075d51900a100000000000000920d1a00a200000000000000ec161a00a300000000000000b6451a00a400000000000000887d1a00a50000000000000077b51a00a600000000000000cdbe1a00a70000000000000070ed1a00a80000000000000083091b00a9000000000000004e251b00aa00000000000000fe371b00ab00000000000000065d1b00ac000000000000005f661b00ad00000000000000bd6f1b00ae00000000000000de941b00af00000000000000fecc1b00b0000000000000001f041c00b1000000000000000c321c00b2000000000000002f3b1c00b3000000000000002e721c00b4000000000000000ca01c00b50000000000000044a91c00b60000000000000022e11c00b70000000000000044191d00b8000000000000000c481d00b9000000000000006b511d00ba000000000000008b891d00bb00000000000000a5c11d00bc0000000000000053f91d00bd00000000000000ff301e00be00000000000000054d1e00bf0000000000000002691e00c000000000000000d1a01e00c100000000000000c5d81e00c200000000000000cf101f00c30000000000000083481f00c400000000000000af801f00c500000000000000d0b81f00c600000000000000f0f01f00c7000000000000001b292000c80000000000000039612000c90000000000000054992000ca000000000000004fd12000cb000000000000004c092100cc00000000000000031c2100cd000000000000006d412100ce00000000000000cc4a2100cf0000000000000098792100d000000000000000c4b12100d100000000000000eee92100d20000000000000011222200d300000000000000325a2200d40000000000000055922200d50000000000000075ca2200d6000000000000008f022300d700000000000000b13a2300d800000000000000cd722300d90000000000000078852300da00000000000000ce8e2300db00000000000000bdaa2300dc00000000000000abe22300dd0000000000000012112400de00000000000000501a2400df0000000000000045512400e000000000000000a1882400e1000000000000005fc02400e20000000000000013f82400e30000000000000007302500e40000000000000013682500e500000000000000c37a2500e600000000000000a8962500e700000000000000fb9f2500e80000000000000000d82500e90000000000000019102600ea000000000000002b482600eb0000000000000028802600ec000000000000002eb82600ed0000000000000044d42600ee0000000000000058f02600ef00000000000000b3f92600f00000000000000065282700f10000000000000057602700f20000000000000064982700f3000000000000008dd02700f400000000000000a7ec2700f500000000000000b9082800f600000000000000e0402800f700000000000000f6782800f80000000000000019b12800f90000000000000040e92800fa000000000000006c212900fb00000000000000a0592900fc00000000000000107f2900fd00000000000000bc912900fe00000000000000eac92900ff00000000000000fd012a000001000000000000ff1d2a0001010000000000000c3a2a0002010000000000002b722a00030100000000000005aa2a000401000000000000fce12a0005010000000000004ceb2a000601000000000000e0fd2a000701000000000000c3192b000801000000000000be512b0009010000000000000a772b000a01000000000000ae892b000b01000000000000b0a52b000c01000000000000abc12b000d010000000000009bf92b000e0100000000000093312c000f0100000000000087692c00100100000000000075a12c00110100000000000074d92c00120100000000000089112d00130100000000000099492d001401000000000000b0812d001501000000000000c3b92d001601000000000000d1f12d001701000000000000d6292e001801000000000000e9612e001901000000000000ea992e001a01000000000000efd12e001b01000000000000f8092f001c01000000000000f0412f001d01000000000000e9792f001e0100000000000036832f001f01000000000000b2b12f002001000000000000a9cd2f00210100000000000094e92f0022010000000000007121300023010000000000003b5930002401000000000000089130002501000000000000599a30002601000000000000f6c830002701000000000000e30031002801000000000000c03831002901000000000000a17031002a01000000000000f27931002b010000000000007fa831002c010000000000005de031002d01000000000000aae931002e01000000000000441832002f01000000000000295032003001000000000000fe8732003101000000000000aa9a3200320100000000000010c0320033010000000000003af8320034010000000000005f303300350100000000000059683300360100000000000078a0330037010000000000009bd833003801000000000000cb1034003901000000000000f44834003a010000000000001c8134003b0100000000000044b934003c0100000000000055f134003d010000000000009dfa34003e01000000000000302935003f01000000000000c6573500400100000000000023613500410100000000000053993500420100000000000080d135004301000000000000560036004401000000000000b10936004501000000000000ce4136004601000000000000037a3600470100000000000031b2360048010000000000005fea360049010000000000007b2237004a01000000000000995a37004b01000000000000f56337004c01000000000000c69237004d01000000000000feca37004e01000000000000340338004f01000000000000683b380050010000000000009e7338005101000000000000c9ab38005201000000000000dcc7380053010000000000003cd138005401000000000000f8e338005501000000000000b0f6380056010000000000001c1c390057010000000000007a2539005801000000000000da2e39005901000000000000525439005a01000000000000878c39005b01000000000000bbc439005c01000000000000f3fc39005d0100000000000028353a005e010000000000005f6d3a005f0100000000000098a53a006001000000000000cedd3a0061010000000000000c163b006201000000000000404e3b00630100000000000019853b006401000000000000608e3b006501000000000000b8973b0066010000000000000fa13b006701000000000000a7b33b006801000000000000fabc3b00690100000000000049c63b006a010000000000009ccf3b006b01000000000000eed83b006c01000000000000c1f43b006d0100000000000014fe3b006e0100000000000066073c006f01000000000000b7103c0070010000000000009e2c3c007101000000000000ee353c00720100000000000094483c007301000000000000e0513c0074010000000000007c643c0075010000000000001d773c0076010000000000004b9c3c00770100000000000010d43c007801000000000000d80b3d0079010000000000001a153d007a0100000000000053433d007b01000000000000ea553d007c01000000000000225f3d007d0100000000000072683d007e01000000000000b4713d007f01000000000000fb7a3d0080010000000000007a8d3d008101000000000000b8963d00820100000000000006a03d00830100000000000088b23d008401000000000000c8bb3d0085010000000000000bc53d0086010000000000001dea3d008701000000000000e9053e008801000000000000b5213e0089010000000000003b343e008a01000000000000843d3e008b010000000000005e593e008c010000000000001f913e008d0100000000000065c83e008e010000000000006bed3e008f01000000000000a9f63e009001000000000000f6ff3e009101000000000000c1373f0092010000000000005c4a3f0093010000000000003b663f009401000000000000856f3f009501000000000000cf783f0096010000000000003ea73f009701000000000000ccde3f0098010000000000008516400099010000000000001e2940009a010000000000006e4e40009b01000000000000c35740009c010000000000009b8640009d01000000000000cebe40009e0100000000000001f740009f01000000000000372f4100a00100000000000097384100a10100000000000070674100a201000000000000a99f4100a30100000000000065b24100a401000000000000ddd74100a50100000000000096ea4100a6010000000000000b104200a70100000000000044484200a8010000000000009c514200a9010000000000003b804200aa0100000000000051b84200ab010000000000006fd44200ac010000000000005ef04200ad01000000000000b9f94200ae010000000000006a284300af0100000000000078604300b00100000000000077984300b101000000000000abd04300b20100000000000064e34300b30100000000000072ff4300b401000000000000d2084400b50100000000000008414400b6010000000000002e794400b7010000000000005eb14400b8010000000000007de94400b9010000000000009e214500ba010000000000005d344500bb01000000000000d0594500bc0100000000000006924500bd010000000000001aca4500be010000000000004a024600bf01000000000000603a4600c00100000000000084724600c101000000000000abaa4600c20100000000000047bd4600c3010000000000009ec64600c401000000000000a0e24600c5010000000000005df54600c601000000000000bf1a4700c701000000000000d1524700c8010000000000007f814700c901000000000000dd8a4700ca0100000000000039944700cb01000000000000f2c24700cc0100000000000010fb4700cd01000000000000d5294800ce010000000000002c334800cf01000000000000f9614800d001000000000000596b4800d10100000000000078874800d2010000000000008da34800d301000000000000aadb4800d401000000000000c6134900d501000000000000eb4b4900d601000000000000e7834900d701000000000000f9bb4900d801000000000000b6ce4900d9010000000000001bf44900da010000000000004a2c4a00db0100000000000066644a00dc010000000000002f7d4a00dd0100000000000019994a00de01000000000000c0ab4a00df01000000000000aec74a00e001000000000000fed04a00e101000000000000bbff4a00e20100000000000019094b00e301000000000000902e4b00e40100000000000041414b00e50100000000000010704b00e6010000000000006e794b00e7010000000000002b8c4b00e80100000000000094b14b00e901000000000000a4e94b00ea01000000000000d4214c00eb01000000000000d7594c00ec01000000000000e8914c00ed0100000000000004ae4c00ee01000000000000ebc94c00ef0100000000000014024d00f001000000000000fe394d00f1010000000000000a724d00f201000000000000667b4d00f30100000000000013aa4d00f40100000000000031c64d00f50100000000000037e24d00f6010000000000004afe4d00f7010000000000002c1a4e00f801000000000000ea2c4e00f90100000000000049364e00fa010000000000004e524e00fb01000000000000628a4e00fc0100000000000079a64e00fd010000000000001ab94e00fe0100000000000079c24e00ff0100000000000094de4e000002000000000000aafa4e00010200000000000059324f00020200000000000004654f000302000000000000ff764f0004020000000000000d804f0005020000000000007e924f000602000000000000c29b4f000702000000000000f4d34f000802000000000000160c50000902000000000000504450000a02000000000000877c50000b02000000000000b6b450000c02000000000000e7ec50000d0200000000000046f650000e02000000000000b61b51000f020000000000001625510010020000000000004f5d510011020000000000000f7051001202000000000000889551001302000000000000b5cd5100140200000000000014d751001502000000000000e605520016020000000000001f3e5200170200000000000053765200180200000000000089ae52001902000000000000e8b752001a02000000000000b7e652001b0200000000000074f952001c02000000000000e81e53001d020000000000001a5753001e02000000000000558f53001f020000000000008ac753002002000000000000b9ff53002102000000000000f13754002202000000000000277054002302000000000000418c54002402000000000000d1a354002502000000000000d9c8540026020000000000007edb54002702000000000000b81355002802000000000000e34b55002902000000000000c58355002a02000000000000d6bb55002b0200000000000007f455002c02000000000000c30656002d020000000000002c2c56002e020000000000005d6456002f020000000000008f9c56003002000000000000c9d456003102000000000000070d570032020000000000004345570033020000000000007a7d570034020000000000007d99570035020000000000009ab557003602000000000000b4ed57003702000000000000f225580038020000000000002f5e580039020000000000006b9658003a02000000000000a6ce58003b02000000000000e30659003c02000000000000183f59003d02000000000000517759003e02000000000000ad8059003f020000000000008baf59004002000000000000e9b859004102000000000000c5e75900420200000000000002205a0043020000000000003f585a0044020000000000007c905a004502000000000000bcc85a004602000000000000f1005b004702000000000000111d5b00480200000000000030395b0049020000000000006f715b004a02000000000000aca95b004b02000000000000e9e15b004c02000000000000251a5c004d0200000000000060525c004e020000000000009f8a5c004f02000000000000dbc25c00500200000000000019fb5c00510200000000000058335d005202000000000000956b5d005302000000000000c7a35d005402000000000000f7db5d00550200000000000031145e0056020000000000006f4c5e005702000000000000a7845e005802000000000000e0bc5e0059020000000000003fc65e005a020000000000001cf55e005b02000000000000582d5f005c0200000000000093655f005d02000000000000cf9d5f005e0200000000000005d65f005f02000000000000440e600060020000000000008346600061020000000000006a7e6000620200000000000056b46000630200000000000000ec60006402000000000000a72361006502000000000000e25b61006602000000000000f293610067020000000000001bcc61006802000000000000dade61006902000000000000590462006a02000000000000963c62006b02000000000000cc7462006c020000000000008c8762006d02000000000000ffac62006e020000000000003ae562006f02000000000000731d63007002000000000000b05563007102000000000000e98d630072020000000000001dc6630073020000000000005dfe63007402000000000000993664007502000000000000d86e6400760200000000000017a76400770200000000000051df640078020000000000008a1765007902000000000000c34f65007a02000000000000018865007b020000000000003ec065007c020000000000007af865007d02000000000000b63066007e02000000000000f06866007f0200000000000004a16600800200000000000041d966008102000000000000711167008202000000000000ac4967008302000000000000de8167008402000000000000f8b967008502000000000000b8cc6700860200000000000035f2670087020000000000006e2a680088020000000000001c3d680089020000000000007f6268008a02000000000000ba9a68008b02000000000000f3d268008c02000000000000310b69008d02000000000000704369008e02000000000000ae7b69008f02000000000000eeb3690090020000000000002bec6900910200000000000065246a009202000000000000a45c6a009302000000000000e0946a0094020000000000001dcd6a009502000000000000dbdf6a00960200000000000059056b00970200000000000018186b009802000000000000923d6b009902000000000000b0756b009a02000000000000e6ad6b009b0200000000000021e66b009c020000000000005e1e6c009d0200000000000096566c009e02000000000000d28e6c009f020000000000000ac76c00a00200000000000047ff6c00a10200000000000077376d00a202000000000000876f6d00a3020000000000000fa76d00a40200000000000059dc6d00a50200000000000022146e00a602000000000000464c6e00a70200000000000071846e00a802000000000000eea96e00a902000000000000aabc6e00aa0200000000000085eb6e00ab02000000000000e4f46e00ac020000000000001c2d6f00ad02000000000000da3f6f00ae0200000000000053656f00af020000000000008c9d6f00b002000000000000c4d56f00b102000000000000d90d7000b202000000000000d7457000b302000000000000f67d7000b402000000000000deb57000b502000000000000b2ed7000b602000000000000a9257100b702000000000000975d7100b802000000000000338c7100b9020000000000007e957100ba0200000000000068b17100bb0200000000000050cd7100bc020000000000001c057200bd02000000000000610e7200be02000000000000c13c7200bf020000000000006b747200c0020000000000005aac7200c10200000000000032e47200c202000000000000dcf67200c302000000000000321c7300c4020000000000002b547300c5020000000000007d8b7300c60200000000000020c37300c702000000000000cefa7300c8020000000000003c327400c9020000000000009b697400ca02000000000000eda07400cb0200000000000056d87400cc0200000000000090107500cd02000000000000ad2c7500ce020000000000000b367500cf02000000000000c7487500d002000000000000fe807500d10200000000000039b97500d20200000000000073f17500d30200000000000030047600d4020000000000004b207600d502000000000000a9297600d60200000000000006337600d702000000000000d3617600d80200000000000090747600d902000000000000089a7600da020000000000002fd27600db020000000000001a0a7700dc0200000000000022427700dd02000000000000007a7700de02000000000000d2b17700df02000000000000f8e97700e0020000000000002b227800e102000000000000635a7800e202000000000000a0927800e302000000000000daca7800e40200000000000011037900e502000000000000483b7900e60200000000000085737900e702000000000000b1ab7900e802000000000000dae37900e902000000000000121c7a00ea0200000000000049547a00eb02000000000000878c7a00ec02000000000000bfc47a00ed02000000000000edfc7a00ee0200000000000026357b00ef02000000000000606d7b00f0020000000000009da57b00f102000000000000cddd7b00f20200000000000006167c00f3020000000000003f4e7c00f402000000000000fb607c00f50200000000000077867c00f602000000000000b4be7c00f70200000000000014c87c00f802000000000000e0f67c00f9020000000000001b2f7d00fa0200000000000058677d00fb02000000000000959f7d00fc02000000000000d2d77d00fd02000000000000ec0f7e00fe0200000000000025487e00ff020000000000005f807e0000030000000000009ab87e000103000000000000d3f07e000203000000000000ee0c7f0003030000000000000a297f000403000000000000c53b7f00050300000000000043617f0006030000000000007b997f000703000000000000b9d17f000803000000000000f20980000903000000000000284280000a030000000000005e7a80000b0300000000000099b280000c03000000000000d2ea80000d03000000000000082381000e030000000000003e5b81000f030000000000007b9381001003000000000000b8cb81001103000000000000f30382001203000000000000313c82001303000000000000697482001403000000000000a6ac82001503000000000000c4c882001603000000000000e0e482001703000000000000ff00830018030000000000001e1d83001903000000000000dd2f83001a030000000000005b5583001b03000000000000988d83001c03000000000000d5c583001d0300000000000010fe83001e030000000000004e3684001f03000000000000826e84002003000000000000bba684002103000000000000f5de840022030000000000006f0485002303000000000000cc0d850024030000000000002c1785002503000000000000ea2985002603000000000000634f850027030000000000007e6b850028030000000000009a878500290300000000000017ad85002a03000000000000d2bf85002b0300000000000031c985002c030000000000000ef885002d030000000000004a3086002e03000000000000866886002f03000000000000bea086003003000000000000f2d8860031030000000000002a1187003203000000000000871a870033030000000000006449870034030000000000001d5c87003503000000000000998187003603000000000000cfb987003703000000000000eed5870038030000000000000cf2870039030000000000004a2a88003a03000000000000a83388003b03000000000000826288003c03000000000000b69a88003d03000000000000efd288003e030000000000002d0b89003f030000000000004d27890040030000000000006c4389004103000000000000ab7b89004203000000000000eab38900430300000000000028ec8900440300000000000068248a004503000000000000a05c8a004603000000000000b4948a004703000000000000f4cc8a00480300000000000030058b0049030000000000006f3d8b004a030000000000008e598b004b03000000000000ae758b004c03000000000000ecad8b004d0300000000000028e68b004e03000000000000331e8c004f030000000000004f568c0050030000000000008e8e8c005103000000000000c7c68c00520300000000000005ff8c00530300000000000041378d005403000000000000746f8d005503000000000000a4a78d00560300000000000064ba8d005703000000000000e4df8d0058030000000000000a188e00590300000000000023508e005a0300000000000027888e005b03000000000000d89a8e005c0300000000000043c08e005d0300000000000082f88e005e03000000000000c0308f005f03000000000000ff688f0060030000000000001ba18f00610300000000000059d98f006203000000000000981190006303000000000000d64990006403000000000000f56590006503000000000000158290006603000000000000758b9000670300000000000053ba9000680300000000000092f290006903000000000000d22a91006a03000000000000106391006b03000000000000489b91006c03000000000000a2a491006d030000000000001bd391006e03000000000000530992006f03000000000000d32e9200700300000000000090419200710300000000000074799200720300000000000094b19200730300000000000072e092007403000000000000d2e992007503000000000000b21893007603000000000000122293007703000000000000445a93007803000000000000739293007903000000000000f3b793007a03000000000000abca93007b030000000000005ddd93007c03000000000000c40294007d03000000000000e13a94007e03000000000000217394007f0300000000000059ab9400800300000000000090e394008103000000000000c31b95008203000000000000ea53950083030000000000009866950084030000000000000b8c9500850300000000000046c49500860300000000000057fc950087030000000000008f3496008803000000000000cf6c960089030000000000000ba596008a0300000000000045dd96008b03000000000000a3e696008c03000000000000801597008d03000000000000bc4d97008e03000000000000f78597008f030000000000002ebe9700900300000000000030f6970091030000000000005a2e98009203000000000000956698009303000000000000d49e9800940300000000000014d7980095030000000000003b0f990096030000000000006c4799009703000000000000ac7f9900980300000000000078b79900990300000000000026ca99009a030000000000007cef99009b0300000000000085279a009c03000000000000be5f9a009d03000000000000fd979a009e03000000000000b9aa9a009f0300000000000022d09a00a0030000000000003dec9a00a10300000000000058089b00a20300000000000074249b00a3030000000000008b409b00a403000000000000e4499b00a50300000000000038789b00a60300000000000076819b00a703000000000000e4af9b00a803000000000000b7e79b00a903000000000000731f9c00aa03000000000000a6289c00ab030000000000002f3b9c00ac0300000000000012579c00ad030000000000005d609c00ae03000000000000cb8e9c00af0300000000000057a19c00b00300000000000086c69c00b1030000000000005afe9c00b20300000000000002369d00b303000000000000bc6d9d00b40300000000000099a59d00b5030000000000004edd9d00b603000000000000db149e00b703000000000000e0399e00b803000000000000724c9e00b9030000000000002a849e00ba03000000000000ee9f9e00bb03000000000000d1bb9e00bc030000000000007df39e00bd03000000000000f02a9f00be030000000000006a629f00bf03000000000000ff999f00c0030000000000002ed19f00c1030000000000004608a000c203000000000000893fa000c303000000000000a476a000c403000000000000dfada000c5030000000000001cb7a000c6030000000000003ce5a000c703000000000000921ca100c8030000000000008c53a100c903000000000000988aa100ca0300000000000010a6a100cb03000000000000a0c1a100cc03000000000000e5d3a100cd0300000000000072f8a100ce030000000000007c2fa200cf030000000000003766a200d003000000000000389da200d10300000000000056a6a200d203000000000000a9b8a200d303000000000000cac1a200d4030000000000001ad4a200d503000000000000200ba300d6030000000000002714a300d703000000000000bc41a300d8030000000000006778a300d9030000000000000aafa300da0300000000000046dca300db0300000000000065e5a300dc03000000000000a81ba400dd03000000000000d72da400de030000000000002352a400df030000000000006288a400e003000000000000c1bea400e103000000000000f8f4a400e203000000000000212ba500e3030000000000003f61a500e403000000000000656aa500e503000000000000e497a500e60300000000000040cea500e703000000000000b204a600e803000000000000fc3aa600e9030000000000009471a600ea0300000000000037a8a600eb030000000000001adfa600ec03000000000000ea0ca700ed030000000000000e16a700ee030000000000005228a700ef030000000000007d31a700f003000000000000034da700f1030000000000002084a700f2030000000000004a8da700f303000000000000a99fa700f403000000000000f6baa700f503000000000000c1f1a700f603000000000000be28a800f703000000000000a65fa800f8030000000000003e7ba800f903000000000000c296a800fa03000000000000c3cda800fb03000000000000d504a900fc03000000000000f83ba900fd030000000000005f73a900fe03000000000000ceaaa900ff030000000000000bb4a900000400000000000005e2a90001040000000000005e19aa000204000000000000c12baa0003040000000000008e50aa000404000000000000fd62aa0005040000000000008175aa000604000000000000fa87aa0007040000000000002f91aa0008040000000000005dbfaa000904000000000000a3c8aa000a04000000000000e5f6aa000b04000000000000e41bab000c040000000000005b2eab000d04000000000000e765ab000e040000000000004c9dab000f0400000000000085a6ab001004000000000000b8d4ab001104000000000000fdddab0012040000000000003b0cac001304000000000000d043ac001404000000000000827bac001504000000000000b8a0ac0016040000000000005bb3ac00170400000000000029ebac0018040000000000006af4ac0019040000000000000e07ad001a04000000000000f422ad001b04000000000000432cad001c040000000000009935ad001d04000000000000ee3ead001e04000000000000d55aad001f04000000000000bd76ad002004000000000000a592ad00210400000000000076caad002204000000000000f6dcad002304000000000000e001ae0024040000000000004f39ae0025040000000000001371ae0026040000000000005f7aae002704000000000000fc8cae002804000000000000cda8ae0029040000000000005ebbae002a0400000000000081e0ae002b040000000000004f18af002c040000000000001e50af002d04000000000000e687af002e04000000000000a0bfaf002f040000000000005ff7af003004000000000000042fb0003104000000000000da66b00032040000000000009a9eb000330400000000000063d6b0003404000000000000300eb1003504000000000000da45b10036040000000000009a7db100370400000000000050b5b100380400000000000029edb1003904000000000000971bb2003a04000000000000e024b2003b04000000000000995cb2003c040000000000006694b2003d0400000000000048b0b2003e040000000000002eccb2003f0400000000000075d5b200400400000000000008e8b2004104000000000000e703b3004204000000000000ce1fb3004304000000000000b63bb30044040000000000000d45b30045040000000000009f57b30046040000000000007573b3004704000000000000c67cb30048040000000000003aabb3004904000000000000e4e2b3004a04000000000000651ab4004b04000000000000f951b4004c040000000000009389b4004d0400000000000025c1b4004e04000000000000f6f8b4004f04000000000000241eb5005004000000000000b130b50051040000000000007068b500520400000000000040a0b5005304000000000000ecd7b50054040000000000000510b60055040000000000003e48b60056040000000000007a80b6005704000000000000b7b8b6005804000000000000f3f0b60059040000000000002f29b7005a04000000000000ae4eb7005b040000000000006861b7005c04000000000000a599b7005d04000000000000ded1b7005e040000000000005cf7b7005f04000000000000160ab80060040000000000005042b8006104000000000000964bb8006204000000000000687ab8006304000000000000a6b2b800640400000000000066c5b8006504000000000000e5eab80066040000000000000423b90067040000000000003f5bb90068040000000000005d77b90069040000000000007b93b9006a04000000000000b7cbb9006b04000000000000ef03ba006c04000000000000133cba006d040000000000003358ba006e040000000000005174ba006f0400000000000042acba0070040000000000006ce4ba007104000000000000a21cbb007204000000000000e054bb007304000000000000405ebb0074040000000000001b8dbb0075040000000000002ec5bb0076040000000000006dfdbb007704000000000000a435bc007804000000000000d06dbc0079040000000000000ca6bc007a040000000000004adebc007b040000000000008716bd007c04000000000000c34ebd007d04000000000000fc86bd007e040000000000003bbfbd007f040000000000007af7bd008004000000000000d500be008104000000000000b32fbe008204000000000000ea67be00830400000000000027a0be00840400000000000065d8be008504000000000000a410bf008604000000000000dd48bf0087040000000000003b52bf0088040000000000001881bf0089040000000000008fb8bf008a04000000000000cbc1bf008b04000000000000f8efbf008c040000000000007602c0008d040000000000008327c0008e04000000000000075fc0008f040000000000005d96c000900400000000000009cec00091040000000000003b06c10092040000000000002d3ec10093040000000000006476c10094040000000000007aaec1009504000000000000b9e6c1009604000000000000ef1ec20097040000000000002c57c2009804000000000000698fc20099040000000000008cc7c2009a040000000000009effc2009b04000000000000da37c3009c04000000000000ee6fc3009d0400000000000029a8c3009e0400000000000067e0c3009f04000000000000240fc400a0040000000000008218c400a104000000000000b150c400a204000000000000c088c400a304000000000000d2c0c400a404000000000000f6f8c400a5040000000000001231c500a604000000000000d143c500a7040000000000004d69c500a80400000000000089a1c500a904000000000000c4d9c500aa040000000000000112c600ab040000000000005c1bc600ac040000000000003a4ac600ad040000000000007482c600ae04000000000000abbac600af04000000000000e4f2c600b0040000000000001d2bc700b1040000000000002e47c700b2040000000000004863c700b304000000000000687fc700b404000000000000829bc700b5040000000000009bd3c700b604000000000000d80bc800b7040000000000001144c800b804000000000000704dc800b904000000000000d056c800ba040000000000004e7cc800bb0400000000000080b4c800bc04000000000000b1ecc800bd040000000000009808c900be040000000000008d24c900bf04000000000000c75cc900c004000000000000df94c900c104000000000000feb0c900c2040000000000001dcdc900c3040000000000004605ca00c4040000000000006e3dca00c5040000000000009e75ca00c604000000000000029bca00c704000000000000aeadca00c8040000000000008adcca00c904000000000000eae5ca00ca04000000000000251ecb00cb04000000000000fa55cb00cc04000000000000778ccb00cd04000000000000eec3cb00ce0400000000000005fccb00cf040000000000004134cc00d004000000000000716ccc00d10400000000000096a4cc00d204000000000000d3dccc00d30400000000000086efcc00d4040000000000000215cd00d504000000000000ac27cd00d604000000000000264dcd00d7040000000000008656cd00d8040000000000006385cd00d9040000000000003bb4cd00da0400000000000099bdcd00db04000000000000d8f5cd00dc04000000000000172ece00dd040000000000005366ce00de04000000000000909ece00df04000000000000b7d6ce00e00400000000000068e9ce00e104000000000000cc0ecf00e2040000000000000547cf00e304000000000000427fcf00e40400000000000079b7cf00e504000000000000b8efcf00e604000000000000f427d000e7040000000000000b60d000e8040000000000004698d000e90400000000000083d0d000ea04000000000000c008d100eb04000000000000fa40d100ec040000000000003679d100ed0400000000000073b1d100ee0400000000000087cdd100ef04000000000000a6e9d100f004000000000000e521d200f1040000000000001e5ad200f2040000000000005692d200f30400000000000092cad200f40400000000000052ddd200f504000000000000ce02d300f604000000000000e13ad300f7040000000000003444d300f804000000000000dc56d300f904000000000000ef72d300fa040000000000004d7cd300fb0400000000000024abd300fc04000000000000a1d0d300fd040000000000005be3d300fe04000000000000901bd400ff04000000000000ce53d40000050000000000000a8cd40001050000000000003ac4d40002050000000000004ae0d400030500000000000069fcd4000405000000000000a134d50005050000000000006047d5000605000000000000de6cd50007050000000000001ba5d500080500000000000058ddd50009050000000000009415d6000a05000000000000d24dd6000b05000000000000f085d6000c050000000000001ebed6000d05000000000000fbecd6000e050000000000005bf6d6000f050000000000008b2ed7001005000000000000c566d7001105000000000000029fd700120500000000000036d7d70013050000000000006f0fd80014050000000000009f47d8001505000000000000c97fd8001605000000000000e4b7d80017050000000000001ff0d80018050000000000005928d90019050000000000009560d9001a050000000000005473d9001b05000000000000718fd9001c05000000000000d198d9001d0500000000000031a2d9001e050000000000000fd1d9001f05000000000000cfe3d90020050000000000004f09da0021050000000000008941da002205000000000000b979da002305000000000000edb1da00240500000000000047bbda00250500000000000054d7da00260500000000000007eada00270500000000000067f3da0028050000000000003a22db0029050000000000005e5adb002a050000000000007892db002b05000000000000b0cadb002c05000000000000e702dc002d05000000000000183bdc002e050000000000007644dc00" + } + } + \ No newline at end of file diff --git a/artifacts/demo_chain_specs/polkadot_asset_hub.json b/artifacts/demo_chain_specs/polkadot_asset_hub.json new file mode 100644 index 0000000000..6d4266c039 --- /dev/null +++ b/artifacts/demo_chain_specs/polkadot_asset_hub.json @@ -0,0 +1,45 @@ +{ + "name": "Polkadot Asset Hub", + "id": "asset-hub-polkadot", + "chainType": "Live", + "bootNodes": [ + "/ip4/34.65.251.121/tcp/30334/p2p/12D3KooWG3GrM6XKMM4gp3cvemdwUvu96ziYoJmqmetLZBXE8bSa", + "/ip4/34.65.35.228/tcp/30334/p2p/12D3KooWMRyTLrCEPcAQD6c4EnudL3vVzg9zji3whvsMYPUYevpq", + "/dns/polkadot-asset-hub-connect-0.polkadot.io/tcp/30334/p2p/12D3KooWLHqbcQtoBygf7GJgVjVa3TaeLuf7VbicNdooaCmQM2JZ", + "/dns/polkadot-asset-hub-connect-0.polkadot.io/tcp/443/wss/p2p/12D3KooWLHqbcQtoBygf7GJgVjVa3TaeLuf7VbicNdooaCmQM2JZ", + "/dns/polkadot-asset-hub-connect-1.polkadot.io/tcp/30334/p2p/12D3KooWNDrKSayoZXGGE2dRSFW2g1iGPq3fTZE2U39ma9yZGKd3", + "/dns/polkadot-asset-hub-connect-1.polkadot.io/tcp/443/wss/p2p/12D3KooWNDrKSayoZXGGE2dRSFW2g1iGPq3fTZE2U39ma9yZGKd3", + "/dns/polkadot-asset-hub-connect-2.polkadot.io/tcp/30334/p2p/12D3KooWApa2JW4rbLtgzuK7fjLMupLS9HZheX9cdkQKyu6AnGrP", + "/dns/polkadot-asset-hub-connect-2.polkadot.io/tcp/443/wss/p2p/12D3KooWApa2JW4rbLtgzuK7fjLMupLS9HZheX9cdkQKyu6AnGrP", + "/dns/polkadot-asset-hub-connect-3.polkadot.io/tcp/30334/p2p/12D3KooWRsVeHqRs2iKmjLiguxp8myL4G2mDAWhtX2jHwyWujseV", + "/dns/polkadot-asset-hub-connect-3.polkadot.io/tcp/443/wss/p2p/12D3KooWRsVeHqRs2iKmjLiguxp8myL4G2mDAWhtX2jHwyWujseV", + "/dns/boot.stake.plus/tcp/35333/p2p/12D3KooWFrQjYaPZSSLLxEVmoaHFcrF6VoY4awG4KRSLaqy3JCdQ", + "/dns/boot.stake.plus/tcp/35334/wss/p2p/12D3KooWFrQjYaPZSSLLxEVmoaHFcrF6VoY4awG4KRSLaqy3JCdQ", + "/dns/boot.metaspan.io/tcp/16052/p2p/12D3KooWLwiJuvqQUB4kYaSjLenFKH9dWZhGZ4qi7pSb3sUYU651", + "/dns/boot.metaspan.io/tcp/16056/wss/p2p/12D3KooWLwiJuvqQUB4kYaSjLenFKH9dWZhGZ4qi7pSb3sUYU651", + "/dns/boot-cr.gatotech.network/tcp/33110/p2p/12D3KooWKgwQfAeDoJARdtxFNNWfbYmcu6s4yUuSifnNoDgzHZgm", + "/dns/boot-cr.gatotech.network/tcp/35110/wss/p2p/12D3KooWKgwQfAeDoJARdtxFNNWfbYmcu6s4yUuSifnNoDgzHZgm", + "/dns/statemint-bootnode.turboflakes.io/tcp/30315/p2p/12D3KooWL8CyLww3m3pRySQGGYGNJhWDMqko3j5xi67ckP7hDUvo", + "/dns/statemint-bootnode.turboflakes.io/tcp/30415/wss/p2p/12D3KooWL8CyLww3m3pRySQGGYGNJhWDMqko3j5xi67ckP7hDUvo", + "/dns/boot-node.helikon.io/tcp/10220/p2p/12D3KooW9uybhguhDjVJc3U3kgZC3i8rWmAnSpbnJkmuR7C6ZsRW", + "/dns/boot-node.helikon.io/tcp/10222/wss/p2p/12D3KooW9uybhguhDjVJc3U3kgZC3i8rWmAnSpbnJkmuR7C6ZsRW", + "/dns/statemint.bootnode.amforc.com/tcp/30341/p2p/12D3KooWByohP9FXn7ao8syS167qJsbFdpa7fY2Y24xbKtt3r7Ls", + "/dns/statemint.bootnode.amforc.com/tcp/30333/wss/p2p/12D3KooWByohP9FXn7ao8syS167qJsbFdpa7fY2Y24xbKtt3r7Ls", + "/dns/statemint-boot-ng.dwellir.com/tcp/30344/p2p/12D3KooWEFrNuNk8fPdQS2hf34Gmqi6dGSvrETshGJUrqrvfRDZr", + "/dns/statemint-boot-ng.dwellir.com/tcp/443/wss/p2p/12D3KooWEFrNuNk8fPdQS2hf34Gmqi6dGSvrETshGJUrqrvfRDZr" + ], + "telemetryEndpoints": null, + "protocolId": null, + "properties": { + "ss58Format": 0, + "tokenDecimals": 10, + "tokenSymbol": "DOT" + }, + "relay_chain": "polkadot", + "para_id": 1000, + "consensusEngine": null, + "codeSubstitutes": {}, + "genesis": { + "stateRootHash": "0xc1ef26b567de07159e4ecd415fbbb0340c56a09c4d72c82516d0f3bc2b782c80" + } + } \ No newline at end of file diff --git a/lightclient/src/background.rs b/lightclient/src/background.rs index c6ecf935bd..bb0b9b3f3c 100644 --- a/lightclient/src/background.rs +++ b/lightclient/src/background.rs @@ -6,14 +6,16 @@ use futures::stream::StreamExt; use futures_util::future::{self, Either}; use serde::Deserialize; use serde_json::value::RawValue; +use smoldot_light::platform::PlatformRef; use std::{collections::HashMap, str::FromStr}; use tokio::sync::{mpsc, oneshot}; -use super::platform::PlatformType; +use crate::client::AddedChain; + use super::LightClientRpcError; use smoldot_light::ChainId; -const LOG_TARGET: &str = "light-client-background"; +const LOG_TARGET: &str = "subxt-light-client-background"; /// The response of an RPC method. pub type MethodResponse = Result, LightClientRpcError>; @@ -34,6 +36,8 @@ pub enum FromSubxt { params: String, /// Channel used to send back the result. sender: oneshot::Sender, + /// The ID of the chain used to identify the chain. + chain_id: ChainId, }, /// The RPC subscription (pub/sub) request. Subscription { @@ -43,24 +47,21 @@ pub enum FromSubxt { params: String, /// Channel used to send back the subscription ID if successful. sub_id: oneshot::Sender, - /// Channel used to send back the notifcations. + /// Channel used to send back the notifications. sender: mpsc::UnboundedSender>, + /// The ID of the chain used to identify the chain. + chain_id: ChainId, }, } /// Background task data. -pub struct BackgroundTask { +pub struct BackgroundTask { /// Smoldot light client implementation that leverages the exposed platform. - client: smoldot_light::Client, - /// The ID of the chain used to identify the chain protocol (ie. substrate). - /// - /// Note: A single chain is supported for a client. This aligns with the subxt's - /// vision of the Client. - chain_id: ChainId, - /// Unique ID for RPC calls. - request_id: usize, + client: smoldot_light::Client, + /// Generates an unique monotonically increasing ID for each chain. + request_id_per_chain: HashMap, /// Map the request ID of a RPC method to the frontend `Sender`. - requests: HashMap>, + requests: HashMap<(usize, smoldot_light::ChainId), oneshot::Sender>, /// Subscription calls first need to make a plain RPC method /// request to obtain the subscription ID. /// @@ -68,23 +69,27 @@ pub struct BackgroundTask { /// not be sent back to the user. /// Map the request ID of a RPC method to the frontend `Sender`. id_to_subscription: HashMap< - usize, + (usize, smoldot_light::ChainId), ( oneshot::Sender, mpsc::UnboundedSender>, ), >, /// Map the subscription ID to the frontend `Sender`. - subscriptions: HashMap>>, + /// + /// The subscription ID is entirely generated by the node (smoldot). Therefore, it is + /// possible for two distinct subscriptions of different chains to have the same subscription ID. + subscriptions: HashMap<(usize, smoldot_light::ChainId), mpsc::UnboundedSender>>, } -impl BackgroundTask { +impl BackgroundTask { /// Constructs a new [`BackgroundTask`]. - pub fn new(client: smoldot_light::Client, chain_id: ChainId) -> BackgroundTask { + pub fn new( + client: smoldot_light::Client, + ) -> BackgroundTask { BackgroundTask { client, - chain_id, - request_id: 1, + request_id_per_chain: Default::default(), requests: Default::default(), id_to_subscription: Default::default(), subscriptions: Default::default(), @@ -92,10 +97,11 @@ impl BackgroundTask { } /// Fetch and increment the request ID. - fn next_id(&mut self) -> usize { - let next = self.request_id; - self.request_id = self.request_id.wrapping_add(1); - next + fn next_id(&mut self, chain_id: smoldot_light::ChainId) -> usize { + let next = self.request_id_per_chain.entry(chain_id).or_insert(1); + let id = *next; + *next = next.wrapping_add(1); + id } /// Handle the registration messages received from the user. @@ -105,27 +111,28 @@ impl BackgroundTask { method, params, sender, + chain_id, } => { - let id = self.next_id(); + let id = self.next_id(chain_id); let request = format!( r#"{{"jsonrpc":"2.0","id":"{}", "method":"{}","params":{}}}"#, id, method, params ); - self.requests.insert(id, sender); + self.requests.insert((id, chain_id), sender); + tracing::trace!(target: LOG_TARGET, "Tracking request id={id} chain={chain_id:?}"); - tracing::trace!(target: LOG_TARGET, "Generated unique id={id} for request={request}"); - - let result = self.client.json_rpc_request(request, self.chain_id); + let result = self.client.json_rpc_request(request, chain_id); if let Err(err) = result { tracing::warn!( target: LOG_TARGET, "Cannot send RPC request to lightclient {:?}", err.to_string() ); + let sender = self .requests - .remove(&id) + .remove(&(id, chain_id)) .expect("Channel is inserted above; qed"); // Send the error back to frontend. @@ -147,20 +154,21 @@ impl BackgroundTask { params, sub_id, sender, + chain_id, } => { // For subscriptions we need to make a plain RPC request to the subscription method. // The server will return as a result the subscription ID. - let id = self.next_id(); + let id = self.next_id(chain_id); let request = format!( r#"{{"jsonrpc":"2.0","id":"{}", "method":"{}","params":{}}}"#, id, method, params ); - self.id_to_subscription.insert(id, (sub_id, sender)); + tracing::trace!(target: LOG_TARGET, "Tracking subscription request id={id} chain={chain_id:?}"); + self.id_to_subscription + .insert((id, chain_id), (sub_id, sender)); - tracing::trace!(target: LOG_TARGET, "Generated unique id={id} for subscription request={request}"); - - let result = self.client.json_rpc_request(request, self.chain_id); + let result = self.client.json_rpc_request(request, chain_id); if let Err(err) = result { tracing::warn!( target: LOG_TARGET, @@ -169,7 +177,7 @@ impl BackgroundTask { ); let (sub_id, _) = self .id_to_subscription - .remove(&id) + .remove(&(id, chain_id)) .expect("Channels are inserted above; qed"); // Send the error back to frontend. @@ -190,54 +198,57 @@ impl BackgroundTask { } /// Parse the response received from the light client and sent it to the appropriate user. - fn handle_rpc_response(&mut self, response: String) { - tracing::trace!(target: LOG_TARGET, "Received from smoldot response={:?}", response); + fn handle_rpc_response(&mut self, chain_id: smoldot_light::ChainId, response: String) { + tracing::trace!(target: LOG_TARGET, "Received from smoldot response={response} chain={chain_id:?}"); match RpcResponse::from_str(&response) { Ok(RpcResponse::Error { id, error }) => { let Ok(id) = id.parse::() else { - tracing::warn!(target: LOG_TARGET, "Cannot send error. Id={id} is not a valid number"); + tracing::warn!(target: LOG_TARGET, "Cannot send error. Id={id} chain={chain_id:?} is not a valid number"); return; }; - if let Some(sender) = self.requests.remove(&id) { + if let Some(sender) = self.requests.remove(&(id, chain_id)) { if sender .send(Err(LightClientRpcError::Request(error.to_string()))) .is_err() { tracing::warn!( target: LOG_TARGET, - "Cannot send method response to id={id}", + "Cannot send method response to id={id} chain={chain_id:?}", ); } - } else if let Some((sub_id_sender, _)) = self.id_to_subscription.remove(&id) { + } else if let Some((sub_id_sender, _)) = + self.id_to_subscription.remove(&(id, chain_id)) + { if sub_id_sender .send(Err(LightClientRpcError::Request(error.to_string()))) .is_err() { tracing::warn!( target: LOG_TARGET, - "Cannot send method response to id {:?}", - id + "Cannot send method response to id {id} chain={chain_id:?}", ); } } } Ok(RpcResponse::Method { id, result }) => { let Ok(id) = id.parse::() else { - tracing::warn!(target: LOG_TARGET, "Cannot send response. Id={id} is not a valid number"); + tracing::warn!(target: LOG_TARGET, "Cannot send response. Id={id} chain={chain_id:?} is not a valid number"); return; }; // Send the response back. - if let Some(sender) = self.requests.remove(&id) { + if let Some(sender) = self.requests.remove(&(id, chain_id)) { if sender.send(Ok(result)).is_err() { tracing::warn!( target: LOG_TARGET, - "Cannot send method response to id={id}", + "Cannot send method response to id={id} chain={chain_id:?}", ); } - } else if let Some((sub_id_sender, sender)) = self.id_to_subscription.remove(&id) { + } else if let Some((sub_id_sender, sender)) = + self.id_to_subscription.remove(&(id, chain_id)) + { let Ok(sub_id) = result .get() .trim_start_matches('"') @@ -246,41 +257,51 @@ impl BackgroundTask { else { tracing::warn!( target: LOG_TARGET, - "Subscription id={result} is not a valid number", + "Subscription id={result} chain={chain_id:?} is not a valid number", ); return; }; - tracing::trace!(target: LOG_TARGET, "Received subscription id={sub_id}"); + tracing::trace!(target: LOG_TARGET, "Received subscription id={sub_id} chain={chain_id:?}"); if sub_id_sender.send(Ok(result)).is_err() { tracing::warn!( target: LOG_TARGET, - "Cannot send method response to id={id}", + "Cannot send method response to id={id} chain={chain_id:?}", ); } else { // Track this subscription ID if send is successful. - self.subscriptions.insert(sub_id, sender); + self.subscriptions.insert((sub_id, chain_id), sender); } + } else { + tracing::warn!( + target: LOG_TARGET, + "Response id={id} chain={chain_id:?} is not tracked", + ); } } Ok(RpcResponse::Subscription { method, id, result }) => { let Ok(id) = id.parse::() else { - tracing::warn!(target: LOG_TARGET, "Cannot send subscription. Id={id} is not a valid number"); + tracing::warn!(target: LOG_TARGET, "Cannot send subscription. Id={id} chain={chain_id:?} is not a valid number"); return; }; - if let Some(sender) = self.subscriptions.get_mut(&id) { + if let Some(sender) = self.subscriptions.get_mut(&(id, chain_id)) { // Send the current notification response. if sender.send(result).is_err() { tracing::warn!( target: LOG_TARGET, - "Cannot send notification to subscription id={id} method={method}", + "Cannot send notification to subscription id={id} chain={chain_id:?} method={method}", ); // Remove the sender if the subscription dropped the receiver. - self.subscriptions.remove(&id); + self.subscriptions.remove(&(id, chain_id)); } + } else { + tracing::warn!( + target: LOG_TARGET, + "Subscription response id={id} chain={chain_id:?} is not tracked", + ); } } Err(err) => { @@ -295,17 +316,22 @@ impl BackgroundTask { pub async fn start_task( &mut self, from_subxt: mpsc::UnboundedReceiver, - from_node: smoldot_light::JsonRpcResponses, + from_node: Vec, ) { let from_subxt_event = tokio_stream::wrappers::UnboundedReceiverStream::new(from_subxt); - let from_node_event = futures_util::stream::unfold(from_node, |mut from_node| async { - from_node.next().await.map(|result| (result, from_node)) + + let from_node = from_node.into_iter().map(|rpc| { + Box::pin(futures::stream::unfold(rpc, |mut rpc| async move { + let response = rpc.rpc_responses.next().await; + Some(((response, rpc.chain_id), rpc)) + })) }); + let stream_combinator = futures::stream::select_all(from_node); - tokio::pin!(from_subxt_event, from_node_event); + tokio::pin!(from_subxt_event, stream_combinator); let mut from_subxt_event_fut = from_subxt_event.next(); - let mut from_node_event_fut = from_node_event.next(); + let mut from_node_event_fut = stream_combinator.next(); loop { match future::select(from_subxt_event_fut, from_node_event_fut).await { @@ -328,6 +354,10 @@ impl BackgroundTask { } // Message received from rpc handler: lightclient response. Either::Right((node_message, previous_fut)) => { + let Some((node_message, chain)) = node_message else { + tracing::trace!(target: LOG_TARGET, "Smoldot closed all RPC channels"); + break; + }; // Smoldot returns `None` if the chain has been removed (which subxt does not remove). let Some(response) = node_message else { tracing::trace!(target: LOG_TARGET, "Smoldot RPC responses channel closed"); @@ -335,15 +365,15 @@ impl BackgroundTask { }; tracing::trace!( target: LOG_TARGET, - "Received smoldot RPC result {:?}", - response + "Received smoldot RPC chain {:?} result {:?}", + chain, response ); - self.handle_rpc_response(response); + self.handle_rpc_response(chain, response); // Advance backend, save frontend. from_subxt_event_fut = previous_fut; - from_node_event_fut = from_node_event.next(); + from_node_event_fut = stream_combinator.next(); } } } diff --git a/lightclient/src/client.rs b/lightclient/src/client.rs index 62bd65172b..69a1946316 100644 --- a/lightclient/src/client.rs +++ b/lightclient/src/client.rs @@ -2,6 +2,8 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. +use std::iter; + use super::{ background::{BackgroundTask, FromSubxt, MethodResponse}, LightClientRpcError, @@ -11,7 +13,29 @@ use tokio::sync::{mpsc, mpsc::error::SendError, oneshot}; use super::platform::build_platform; -pub const LOG_TARGET: &str = "light-client"; +pub const LOG_TARGET: &str = "subxt-light-client"; + +/// A raw light-client RPC implementation that can connect to multiple chains. +#[derive(Clone)] +pub struct RawLightClientRpc { + /// Communicate with the backend task that multiplexes the responses + /// back to the frontend. + to_backend: mpsc::UnboundedSender, +} + +impl RawLightClientRpc { + /// Construct a [`LightClientRpc`] that can communicated with the provided chain. + /// + /// # Note + /// + /// This uses the same underlying instance created by [`LightClientRpc::new_from_client`]. + pub fn for_chain(&self, chain_id: smoldot_light::ChainId) -> LightClientRpc { + LightClientRpc { + to_backend: self.to_backend.clone(), + chain_id, + } + } +} /// The light-client RPC implementation that is used to connect with the chain. #[derive(Clone)] @@ -19,6 +43,8 @@ pub struct LightClientRpc { /// Communicate with the backend task that multiplexes the responses /// back to the frontend. to_backend: mpsc::UnboundedSender, + /// The chain ID to target for requests. + chain_id: smoldot_light::ChainId, } impl LightClientRpc { @@ -31,14 +57,35 @@ impl LightClientRpc { /// /// ## Panics /// - /// Panics if being called outside of `tokio` runtime context. + /// The panic behaviour depends on the feature flag being used: + /// + /// ### Native + /// + /// Panics when called outside of a `tokio` runtime context. + /// + /// ### Web + /// + /// If smoldot panics, then the promise created will be leaked. For more details, see + /// https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.future_to_promise.html. pub fn new( - config: smoldot_light::AddChainConfig<'_, (), impl Iterator>, + config: smoldot_light::AddChainConfig< + '_, + (), + impl IntoIterator, + >, ) -> Result { tracing::trace!(target: LOG_TARGET, "Create light client"); let mut client = smoldot_light::Client::new(build_platform()); + let config = smoldot_light::AddChainConfig { + specification: config.specification, + json_rpc: config.json_rpc, + database_content: config.database_content, + potential_relay_chains: config.potential_relay_chains.into_iter(), + user_data: config.user_data, + }; + let smoldot_light::AddChainSuccess { chain_id, json_rpc_responses, @@ -46,14 +93,48 @@ impl LightClientRpc { .add_chain(config) .map_err(|err| LightClientRpcError::AddChainError(err.to_string()))?; - let (to_backend, backend) = mpsc::unbounded_channel(); - - // `json_rpc_responses` can only be `None` if we had passed `json_rpc: Disabled`. let rpc_responses = json_rpc_responses.expect("Light client RPC configured; qed"); + let raw_client = Self::new_from_client( + client, + iter::once(AddedChain { + chain_id, + rpc_responses, + }), + ); + Ok(raw_client.for_chain(chain_id)) + } + + /// Constructs a new [`RawLightClientRpc`] from the raw smoldot client. + /// + /// Receives a list of RPC objects as a result of calling `smoldot_light::Client::add_chain`. + /// This [`RawLightClientRpc`] can target different chains using [`RawLightClientRpc::for_chain`] method. + /// + /// ## Panics + /// + /// The panic behaviour depends on the feature flag being used: + /// + /// ### Native + /// + /// Panics when called outside of a `tokio` runtime context. + /// + /// ### Web + /// + /// If smoldot panics, then the promise created will be leaked. For more details, see + /// https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.future_to_promise.html. + pub fn new_from_client( + client: smoldot_light::Client, + chains: impl IntoIterator, + ) -> RawLightClientRpc + where + TPlat: smoldot_light::platform::PlatformRef + Clone, + { + let (to_backend, backend) = mpsc::unbounded_channel(); + let chains = chains.into_iter().collect(); + let future = async move { - let mut task = BackgroundTask::new(client, chain_id); - task.start_task(backend, rpc_responses).await; + let mut task = BackgroundTask::new(client); + task.start_task(backend, chains).await; }; #[cfg(feature = "native")] @@ -61,7 +142,12 @@ impl LightClientRpc { #[cfg(feature = "web")] wasm_bindgen_futures::spawn_local(future); - Ok(LightClientRpc { to_backend }) + RawLightClientRpc { to_backend } + } + + /// Returns the chain ID of the current light-client. + pub fn chain_id(&self) -> smoldot_light::ChainId { + self.chain_id } /// Submits an RPC method request to the light-client. @@ -79,6 +165,7 @@ impl LightClientRpc { method, params, sender, + chain_id: self.chain_id, })?; Ok(receiver) @@ -107,8 +194,17 @@ impl LightClientRpc { params, sub_id, sender, + chain_id: self.chain_id, })?; Ok((sub_id_rx, receiver)) } } + +/// The added chain of the light-client. +pub struct AddedChain { + /// The id of the chain. + pub chain_id: smoldot_light::ChainId, + /// Producer of RPC responses for the chain. + pub rpc_responses: smoldot_light::JsonRpcResponses, +} diff --git a/lightclient/src/lib.rs b/lightclient/src/lib.rs index 43869bbc45..3c438579b5 100644 --- a/lightclient/src/lib.rs +++ b/lightclient/src/lib.rs @@ -33,8 +33,18 @@ mod platform; #[allow(unused_imports)] pub use getrandom as _; -pub use client::LightClientRpc; -pub use smoldot_light::{AddChainConfig, AddChainConfigJsonRpc, ChainId}; +pub use client::{AddedChain, LightClientRpc, RawLightClientRpc}; + +/// Re-exports of the smoldot related objects. +pub mod smoldot { + pub use smoldot_light::{ + platform::PlatformRef, AddChainConfig, AddChainConfigJsonRpc, ChainId, Client, + JsonRpcResponses, + }; + + #[cfg(feature = "native")] + pub use smoldot_light::platform::default::DefaultPlatform; +} /// Light client error. #[derive(Debug, thiserror::Error)] diff --git a/subxt/Cargo.toml b/subxt/Cargo.toml index c1968746e1..12e98e3e36 100644 --- a/subxt/Cargo.toml +++ b/subxt/Cargo.toml @@ -114,3 +114,8 @@ tracing-subscriber = { workspace = true } name = "unstable_light_client_tx_basic" path = "examples/unstable_light_client_tx_basic.rs" required-features = ["unstable-light-client", "jsonrpsee"] + +[[example]] +name = "unstable_light_client_parachains" +path = "examples/unstable_light_client_parachains.rs" +required-features = ["unstable-light-client", "jsonrpsee", "native"] diff --git a/subxt/examples/unstable_light_client_parachains.rs b/subxt/examples/unstable_light_client_parachains.rs new file mode 100644 index 0000000000..775d420510 --- /dev/null +++ b/subxt/examples/unstable_light_client_parachains.rs @@ -0,0 +1,101 @@ +use futures::StreamExt; +use std::{iter, num::NonZeroU32}; +use subxt::{ + client::{LightClient, RawLightClient}, + PolkadotConfig, +}; + +// Generate an interface that we can use from the node's metadata. +#[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")] +pub mod polkadot {} + +const POLKADOT_SPEC: &str = include_str!("../../artifacts/demo_chain_specs/polkadot.json"); +const ASSET_HUB_SPEC: &str = + include_str!("../../artifacts/demo_chain_specs/polkadot_asset_hub.json"); + +#[tokio::main] +async fn main() -> Result<(), Box> { + // The smoldot logs are informative: + tracing_subscriber::fmt::init(); + + // Connecting to a parachain is a multi step process. + + // Step 1. Construct a new smoldot client. + let mut client = + subxt_lightclient::smoldot::Client::new(subxt_lightclient::smoldot::DefaultPlatform::new( + "subxt-example-light-client".into(), + "version-0".into(), + )); + + // Step 2. Connect to the relay chain of the parachain. For this example, the Polkadot relay chain. + let polkadot_connection = client + .add_chain(subxt_lightclient::smoldot::AddChainConfig { + specification: POLKADOT_SPEC, + json_rpc: subxt_lightclient::smoldot::AddChainConfigJsonRpc::Enabled { + max_pending_requests: NonZeroU32::new(128).unwrap(), + max_subscriptions: 1024, + }, + potential_relay_chains: iter::empty(), + database_content: "", + user_data: (), + }) + .expect("Light client chain added with valid spec; qed"); + let polkadot_json_rpc_responses = polkadot_connection + .json_rpc_responses + .expect("Light client configured with json rpc enabled; qed"); + let polkadot_chain_id = polkadot_connection.chain_id; + + // Step 3. Connect to the parachain. For this example, the Asset hub parachain. + let assethub_connection = client + .add_chain(subxt_lightclient::smoldot::AddChainConfig { + specification: ASSET_HUB_SPEC, + json_rpc: subxt_lightclient::smoldot::AddChainConfigJsonRpc::Enabled { + max_pending_requests: NonZeroU32::new(128).unwrap(), + max_subscriptions: 1024, + }, + // The chain specification of the asset hub parachain mentions that the identifier + // of its relay chain is `polkadot`. + potential_relay_chains: [polkadot_chain_id].into_iter(), + database_content: "", + user_data: (), + }) + .expect("Light client chain added with valid spec; qed"); + let parachain_json_rpc_responses = assethub_connection + .json_rpc_responses + .expect("Light client configured with json rpc enabled; qed"); + let parachain_chain_id = assethub_connection.chain_id; + + // Step 4. Turn the smoldot client into a raw client. + let raw_light_client = RawLightClient::builder() + .add_chain(polkadot_chain_id, polkadot_json_rpc_responses) + .add_chain(parachain_chain_id, parachain_json_rpc_responses) + .build(client) + .await?; + + // Step 5. Obtain a client to target the relay chain and the parachain. + let polkadot_api: LightClient = + raw_light_client.for_chain(polkadot_chain_id).await?; + let parachain_api: LightClient = + raw_light_client.for_chain(parachain_chain_id).await?; + + // Step 6. Subscribe to the finalized blocks of the chains. + let polkadot_sub = polkadot_api + .blocks() + .subscribe_finalized() + .await? + .map(|block| ("Polkadot", block)); + let parachain_sub = parachain_api + .blocks() + .subscribe_finalized() + .await? + .map(|block| ("AssetHub", block)); + let mut stream_combinator = futures::stream::select(polkadot_sub, parachain_sub); + + while let Some((chain, block)) = stream_combinator.next().await { + let block = block?; + + println!(" Chain {:?} hash={:?}", chain, block.hash()); + } + + Ok(()) +} diff --git a/subxt/src/client/light_client/builder.rs b/subxt/src/client/light_client/builder.rs index 8c02f2f761..da784e5cb8 100644 --- a/subxt/src/client/light_client/builder.rs +++ b/subxt/src/client/light_client/builder.rs @@ -4,9 +4,10 @@ use super::{rpc::LightClientRpc, LightClient, LightClientError}; use crate::backend::rpc::RpcClient; +use crate::client::RawLightClient; use crate::{config::Config, error::Error, OnlineClient}; use std::num::NonZeroU32; -use subxt_lightclient::{AddChainConfig, AddChainConfigJsonRpc, ChainId}; +use subxt_lightclient::{smoldot, AddedChain}; /// Builder for [`LightClient`]. #[derive(Clone, Debug)] @@ -14,7 +15,7 @@ pub struct LightClientBuilder { max_pending_requests: NonZeroU32, max_subscriptions: u32, bootnodes: Option>, - potential_relay_chains: Option>, + potential_relay_chains: Option>, _marker: std::marker::PhantomData, } @@ -77,7 +78,7 @@ impl LightClientBuilder { /// be wrong to connect to the "Kusama" created by user A. pub fn potential_relay_chains( mut self, - potential_relay_chains: impl IntoIterator, + potential_relay_chains: impl IntoIterator, ) -> Self { self.potential_relay_chains = Some(potential_relay_chains.into_iter().collect()); self @@ -88,7 +89,16 @@ impl LightClientBuilder { /// /// ## Panics /// - /// Panics if being called outside of `tokio` runtime context. + /// The panic behaviour depends on the feature flag being used: + /// + /// ### Native + /// + /// Panics when called outside of a `tokio` runtime context. + /// + /// ### Web + /// + /// If smoldot panics, then the promise created will be leaked. For more details, see + /// https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.future_to_promise.html. #[cfg(feature = "jsonrpsee")] pub async fn build_from_url>(self, url: Url) -> Result, Error> { let chain_spec = fetch_url(url.as_ref()).await?; @@ -104,7 +114,7 @@ impl LightClientBuilder { /// /// The chain spec must be obtained from a trusted entity. /// - /// It can be fetched from a trused node with the following command: + /// It can be fetched from a trusted node with the following command: /// ```bash /// curl -H "Content-Type: application/json" -d '{"id":1, "jsonrpc":"2.0", "method": "sync_state_genSyncSpec", "params":[true]}' http://localhost:9944/ | jq .result > res.spec /// ``` @@ -116,7 +126,16 @@ impl LightClientBuilder { /// /// ## Panics /// - /// Panics if being called outside of `tokio` runtime context. + /// The panic behaviour depends on the feature flag being used: + /// + /// ### Native + /// + /// Panics when called outside of a `tokio` runtime context. + /// + /// ### Web + /// + /// If smoldot panics, then the promise created will be leaked. For more details, see + /// https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.future_to_promise.html. pub async fn build(self, chain_spec: &str) -> Result, Error> { let chain_spec = serde_json::from_str(chain_spec) .map_err(|_| Error::LightClient(LightClientError::InvalidChainSpec))?; @@ -136,9 +155,9 @@ impl LightClientBuilder { } } - let config = AddChainConfig { + let config = smoldot::AddChainConfig { specification: &chain_spec.to_string(), - json_rpc: AddChainConfigJsonRpc::Enabled { + json_rpc: smoldot::AddChainConfigJsonRpc::Enabled { max_pending_requests: self.max_pending_requests, max_subscriptions: self.max_subscriptions, }, @@ -147,12 +166,71 @@ impl LightClientBuilder { user_data: (), }; - let rpc_client = RpcClient::new(LightClientRpc::new(config)?); - let online_client = OnlineClient::::from_rpc_client(rpc_client).await?; - Ok(LightClient(online_client)) + let raw_rpc = LightClientRpc::new(config)?; + build_client_from_rpc(raw_rpc).await } } +/// Raw builder for [`RawLightClient`]. +pub struct RawLightClientBuilder { + chains: Vec, +} + +impl Default for RawLightClientBuilder { + fn default() -> Self { + Self { chains: Vec::new() } + } +} + +impl RawLightClientBuilder { + /// Create a new [`RawLightClientBuilder`]. + pub fn new() -> RawLightClientBuilder { + RawLightClientBuilder::default() + } + + /// Adds a new chain to the list of chains synchronized by the light client. + pub fn add_chain( + mut self, + chain_id: smoldot::ChainId, + rpc_responses: smoldot::JsonRpcResponses, + ) -> Self { + self.chains.push(AddedChain { + chain_id, + rpc_responses, + }); + self + } + + /// Construct a [`RawLightClient`] from a raw smoldot client. + /// + /// The provided `chain_id` is the chain with which the current instance of light client will interact. + /// To target a different chain call the [`LightClient::target_chain`] method. + pub async fn build( + self, + client: smoldot::Client, + ) -> Result { + // The raw subxt light client that spawns the smoldot background task. + let raw_rpc: subxt_lightclient::RawLightClientRpc = + subxt_lightclient::LightClientRpc::new_from_client(client, self.chains.into_iter()); + + // The crate implementation of `RpcClientT` over the raw subxt light client. + let raw_rpc = crate::client::light_client::rpc::RawLightClientRpc::from_inner(raw_rpc); + + Ok(RawLightClient { raw_rpc }) + } +} + +/// Build the light client from a raw rpc client. +async fn build_client_from_rpc( + raw_rpc: LightClientRpc, +) -> Result, Error> { + let chain_id = raw_rpc.chain_id(); + let rpc_client = RpcClient::new(raw_rpc); + let client = OnlineClient::::from_rpc_client(rpc_client).await?; + + Ok(LightClient { client, chain_id }) +} + /// Fetch the chain spec from the URL. #[cfg(feature = "jsonrpsee")] async fn fetch_url(url: impl AsRef) -> Result { diff --git a/subxt/src/client/light_client/mod.rs b/subxt/src/client/light_client/mod.rs index 20ff92c54e..a4b116652e 100644 --- a/subxt/src/client/light_client/mod.rs +++ b/subxt/src/client/light_client/mod.rs @@ -8,6 +8,7 @@ mod builder; mod rpc; use crate::{ + backend::rpc::RpcClient, blocks::BlocksClient, client::{OfflineClientT, OnlineClientT}, config::Config, @@ -19,10 +20,13 @@ use crate::{ tx::TxClient, OnlineClient, }; -pub use builder::LightClientBuilder; +pub use builder::{LightClientBuilder, RawLightClientBuilder}; use derivative::Derivative; use subxt_lightclient::LightClientRpcError; +// Re-export smoldot related objects. +pub use subxt_lightclient::smoldot; + /// Light client error. #[derive(Debug, thiserror::Error)] pub enum LightClientError { @@ -51,10 +55,57 @@ pub enum LightClientError { Handshake, } +/// The raw light-client RPC implementation that is used to connect with the chain. +#[derive(Clone)] +pub struct RawLightClient { + raw_rpc: rpc::RawLightClientRpc, +} + +impl RawLightClient { + /// Construct a [`RawLightClient`] using its builder interface. + /// + /// The raw builder is utilized for constructing light-clients from a low + /// level smoldot client. + /// + /// This is especially useful when you want to gain access to the smoldot client. + /// For example, you may want to connect to multiple chains and/or parachains while reusing the + /// same smoldot client under the hood. Or you may want to configure different values for + /// smoldot internal buffers, number of subscriptions and relay chains. + /// + /// # Note + /// + /// If you are unsure, please use [`LightClient::builder`] instead. + pub fn builder() -> RawLightClientBuilder { + RawLightClientBuilder::default() + } + + /// Target a different chain identified by the provided chain ID for requests. + /// + /// The provided chain ID is provided by the `smoldot_light::Client::add_chain` and it must + /// match one of the `smoldot_light::JsonRpcResponses` provided in [`RawLightClientBuilder::add_chain`]. + /// + /// # Note + /// + /// This uses the same underlying instance spawned by the builder. + pub async fn for_chain( + &self, + chain_id: smoldot::ChainId, + ) -> Result, crate::Error> { + let raw_rpc = self.raw_rpc.for_chain(chain_id); + let rpc_client = RpcClient::new(raw_rpc.clone()); + let client = OnlineClient::::from_rpc_client(rpc_client).await?; + + Ok(LightClient { client, chain_id }) + } +} + /// The light-client RPC implementation that is used to connect with the chain. #[derive(Derivative)] #[derivative(Clone(bound = ""))] -pub struct LightClient(OnlineClient); +pub struct LightClient { + client: OnlineClient, + chain_id: smoldot::ChainId, +} impl LightClient { /// Construct a [`LightClient`] using its builder interface. @@ -68,17 +119,17 @@ impl LightClient { /// Return the [`crate::Metadata`] used in this client. fn metadata(&self) -> crate::Metadata { - self.0.metadata() + self.client.metadata() } /// Return the genesis hash. fn genesis_hash(&self) -> ::Hash { - self.0.genesis_hash() + self.client.genesis_hash() } /// Return the runtime version. fn runtime_version(&self) -> crate::backend::RuntimeVersion { - self.0.runtime_version() + self.client.runtime_version() } /// Work with transactions. @@ -115,11 +166,16 @@ impl LightClient { pub fn runtime_api(&self) -> RuntimeApiClient { >::runtime_api(self) } + + /// Returns the chain ID of the current light-client. + pub fn chain_id(&self) -> smoldot::ChainId { + self.chain_id + } } impl OnlineClientT for LightClient { fn backend(&self) -> &dyn crate::backend::Backend { - self.0.backend() + self.client.backend() } } diff --git a/subxt/src/client/light_client/rpc.rs b/subxt/src/client/light_client/rpc.rs index 7c8948c9bd..1186528ec6 100644 --- a/subxt/src/client/light_client/rpc.rs +++ b/subxt/src/client/light_client/rpc.rs @@ -2,17 +2,32 @@ // This file is dual-licensed as Apache-2.0 or GPL-3.0. // see LICENSE for license details. -use super::LightClientError; +use super::{smoldot, LightClientError}; use crate::{ backend::rpc::{RawRpcFuture, RawRpcSubscription, RpcClientT}, error::{Error, RpcError}, }; use futures::StreamExt; use serde_json::value::RawValue; -use subxt_lightclient::{AddChainConfig, ChainId, LightClientRpcError}; use tokio_stream::wrappers::UnboundedReceiverStream; -pub const LOG_TARGET: &str = "light-client"; +pub const LOG_TARGET: &str = "subxt-rpc-light-client"; + +/// The raw light-client RPC implementation that is used to connect with the chain. +#[derive(Clone)] +pub struct RawLightClientRpc(subxt_lightclient::RawLightClientRpc); + +impl RawLightClientRpc { + /// Constructs a new [`RawLightClientRpc`] from a low level [`subxt_lightclient::RawLightClientRpc`]. + pub fn from_inner(client: subxt_lightclient::RawLightClientRpc) -> RawLightClientRpc { + RawLightClientRpc(client) + } + + /// Constructs a new [`LightClientRpc`] that communicates with the provided chain. + pub fn for_chain(&self, chain_id: smoldot::ChainId) -> LightClientRpc { + LightClientRpc(self.0.for_chain(chain_id)) + } +} /// The light-client RPC implementation that is used to connect with the chain. #[derive(Clone)] @@ -28,15 +43,29 @@ impl LightClientRpc { /// /// ## Panics /// - /// Panics if being called outside of `tokio` runtime context. + /// The panic behaviour depends on the feature flag being used: + /// + /// ### Native + /// + /// Panics when called outside of a `tokio` runtime context. + /// + /// ### Web + /// + /// If smoldot panics, then the promise created will be leaked. For more details, see + /// https://docs.rs/wasm-bindgen-futures/latest/wasm_bindgen_futures/fn.future_to_promise.html. pub fn new( - config: AddChainConfig<'_, (), impl Iterator>, + config: smoldot::AddChainConfig<'_, (), impl Iterator>, ) -> Result { let rpc = subxt_lightclient::LightClientRpc::new(config) .map_err(|err| LightClientError::Rpc(err))?; Ok(LightClientRpc(rpc)) } + + /// Returns the chain ID of the current light-client. + pub fn chain_id(&self) -> smoldot::ChainId { + self.0.chain_id() + } } impl RpcClientT for LightClientRpc { @@ -46,6 +75,7 @@ impl RpcClientT for LightClientRpc { params: Option>, ) -> RawRpcFuture<'a, Box> { let client = self.clone(); + let chain_id = self.chain_id(); Box::pin(async move { let params = match params { @@ -66,7 +96,7 @@ impl RpcClientT for LightClientRpc { .await .map_err(|_| RpcError::ClientError(Box::new(LightClientError::BackgroundClosed)))?; - tracing::trace!(target: LOG_TARGET, "RPC response {:?}", response); + tracing::trace!(target: LOG_TARGET, "RPC response={:?} chain={:?}", response, chain_id); response.map_err(|err| RpcError::ClientError(Box::new(err))) }) @@ -79,13 +109,15 @@ impl RpcClientT for LightClientRpc { _unsub: &'a str, ) -> RawRpcFuture<'a, RawRpcSubscription> { let client = self.clone(); + let chain_id = self.chain_id(); Box::pin(async move { tracing::trace!( target: LOG_TARGET, - "Subscribe to {:?} with params {:?}", + "Subscribe to {:?} with params {:?} chain={:?}", sub, - params + params, + chain_id, ); let params = match params { @@ -107,7 +139,7 @@ impl RpcClientT for LightClientRpc { .map_err(|_| RpcError::ClientError(Box::new(LightClientError::BackgroundClosed)))? .map_err(|err| { RpcError::ClientError(Box::new(LightClientError::Rpc( - LightClientRpcError::Request(err.to_string()), + subxt_lightclient::LightClientRpcError::Request(err.to_string()), ))) })?; @@ -116,7 +148,7 @@ impl RpcClientT for LightClientRpc { .trim_start_matches('"') .trim_end_matches('"') .to_string(); - tracing::trace!(target: LOG_TARGET, "Received subscription ID: {}", sub_id); + tracing::trace!(target: LOG_TARGET, "Received subscription={} chain={:?}", sub_id, chain_id); let stream = UnboundedReceiverStream::new(notif); diff --git a/subxt/src/client/mod.rs b/subxt/src/client/mod.rs index 446787d6b1..dbfbdd67d4 100644 --- a/subxt/src/client/mod.rs +++ b/subxt/src/client/mod.rs @@ -20,4 +20,6 @@ pub use online_client::{ }; #[cfg(feature = "unstable-light-client")] -pub use light_client::{LightClient, LightClientBuilder, LightClientError}; +pub use light_client::{ + LightClient, LightClientBuilder, LightClientError, RawLightClient, RawLightClientBuilder, +};