From b7b85096aea0771a1f735f643487c73735ac17f4 Mon Sep 17 00:00:00 2001 From: Willian Mitsuda Date: Mon, 28 Oct 2024 22:43:46 -0300 Subject: [PATCH] Fix panic: runtime error: negative shift amount on eliasfano reverse iterator seek (#12520) Fixes an edge case for the rpc-test `ots_searchTransactionsBefore/test13`. - It occurs on a specially crafted eliasfano sequence on mainnet. - Reverse iterator seeks a value whose upper bit is set at the 63th bit of the 64 bit word. - The seek operation locates the target, but position the cursor at the previous element; but because the way it is coded, the position of the upper part of the value is already positioned at the next element (previous value in this case because of the reverse iterator). I also: - reenabled the rpc-test which was breaking because of this case. - added a similar test for the forward iterator for the sake of completeness (it was NOT breaking, just increasing coverage). --- .../workflows/qa-rpc-integration-tests.yml | 1 - erigon-lib/recsplit/eliasfano32/elias_fano.go | 6 +- .../recsplit/eliasfano32/elias_fano_test.go | 64 +++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa-rpc-integration-tests.yml b/.github/workflows/qa-rpc-integration-tests.yml index 6c4a847b698..5cff99e2567 100644 --- a/.github/workflows/qa-rpc-integration-tests.yml +++ b/.github/workflows/qa-rpc-integration-tests.yml @@ -242,7 +242,6 @@ jobs: ots_getBlockTransactions/test_03.json,\ ots_getBlockTransactions/test_04.json,\ ots_getBlockTransactions/test_05.json,\ - ots_searchTransactionsBefore/test_13.json,\ trace_call/test_05.json,\ trace_call/test_07.json,\ trace_call/test_12.json,\ diff --git a/erigon-lib/recsplit/eliasfano32/elias_fano.go b/erigon-lib/recsplit/eliasfano32/elias_fano.go index 6a503b75eae..37580963e5c 100644 --- a/erigon-lib/recsplit/eliasfano32/elias_fano.go +++ b/erigon-lib/recsplit/eliasfano32/elias_fano.go @@ -405,7 +405,11 @@ func (efi *EliasFanoIter) Seek(n uint64) { // fields of next value efi.lowerIdx -= efi.itemsIterated * efi.l - efi.upperMask = 1 << (sel - 1) + if sel > 0 { + efi.upperMask = 1 << (sel - 1) + } else { + efi.upperMask = 0 + } } else { efi.itemsIterated = nextI diff --git a/erigon-lib/recsplit/eliasfano32/elias_fano_test.go b/erigon-lib/recsplit/eliasfano32/elias_fano_test.go index 88c33fb416c..89ec594603e 100644 --- a/erigon-lib/recsplit/eliasfano32/elias_fano_test.go +++ b/erigon-lib/recsplit/eliasfano32/elias_fano_test.go @@ -25,9 +25,73 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/erigontech/erigon-lib/common/hexutility" "github.com/erigontech/erigon-lib/kv/stream" ) +// This is a very implementation-dependant test using mainnet production data. +// +// Please note that it catches a scenario that is dependent on this data + elias fano parameters hardcoded +// at the time of this writing. +// +// Any changes to the implementation may render this test useless. +func TestEliasFanoSeekBoundaries(t *testing.T) { + raw := "0x" + + "000000000000337e0000000047867de8e14f0e7523b976cdedf4fefd811959209e2df03f5a5195d3bcdb2161246eb5c093e9fc75f4b01ecdf206b27b96ae8bf4540db01ceda733de2a11eb344549aa5ed267bd74aa890cbb8cc49edc16e5c9e833029f028906ea0bf41f2e28802a352d742ee32f7430fc32453403371a393b3b1740eb4159430b48154db94eb550e75bf65bdc5d735e90615762b8640f65f9654f6631674a6801698c710d7a0e7a687e7c839088de8db68e4d91df921c9ab69bb3a0d8a40ca82aa82ba82eabc9ac01b0efb228b677b6e7b8eab842bc46bc7dbc09bf6ac2f8cc4bcea0cf9fd26cd938dee5e45afb30043d056f076412aa134819761aec28da2b38397e3e16423c438f470a48765187589e59575a205d3067eb6f5f77258058800385828552877e89078e569057901896899645a1faa52eab12b249baa7bbb2bf53c1cbc1c6c856cb13cdface6ccf0fe61ae868e9c3ea90eee3ee4aefdaf3ecf714fa7cfb86fdee00e2029403cc09150b410d3f0e6311e51a3b1cc21c5324e438193ae93a5e4049457d46d7465a48e84b174f0d58125e2e605a65a36be770fe730c75ef83e589668d318eb097ce9b239c23a257ad4dae09b212b416b515bfcdbf0ec828ca7ecabecb69ce5ecf38d19fdcf7dcf5e20be33be981ebe3ec75f7c1f732f881f9d1fa05110f2afd2a2637e5430d4a44525b53c25c316306739981de878d882995019c6da994bd4bbea4be60c94de92cf31effb501bf0243039603470ff31f712004214c449e49265181534d5c816d1d86d387758bc6a156a944aa2cad35b440b44dc397c375c6bcc659c7a5cc3dcfdeeabaf36afa6bfa32042a0d51209751fa762ca0f9a560a680a7d2c4fdc8a0cb46d03adbb0def3e2eff4c0f664fdd9ff5d19ed1f96223924c824da26bc2a8b36ef3d9d502e57a659ba685370dd76b97b2f7de57ec28c50bbacbbb1c3e0d182d5f2e0cf017013e4163718a818ce1cbb22f124da278f2fdb301c311c3b87582b59836a23773b771286a5a2a7a7d8a7b4c65dd806dc96ecf6fe0505290f5b1fd622923122350943e546714df459545ae15f9262a666606792857b8979b161bbc0ca02cd97d0b0ee21fd22fd7cfd5107a7099c0ccf27eb2edc44ed5bcf5fa56119757b78287d878f499211a35aaadabc3fc23dd0fdd43ad81ddb31db35dff0025313791f0120a121a245a1637d659f675d7511d815fa3e1e0b3333348b48b34df65d34633c6b0e6fef817288bf8b5592ef9f52ad3eb658c0f6c380e7c7f1ca044109b5112b190841e7428f4dc064c4666b6905763777577c9b81c8882aa2fcacf5b514c617c9d3c95dd4a7d7c1dce5e4dde8130d4912e019e11919296f44114fa059c8730585b5974ca9a3a9eab38db7b6bdaacdf7ce85d4bbd7daea95f796f7e5f8f4fa02030407552c" + + "f2301f408e45764dab58815a7360da67f36b5775fd7f8986d6876889948dab99489ff39ff3a157a58abbbddb45e456ecc7f0e2ff0a1c7336e43ca644c345d3452d596a657c7168782c947ef7defd18133c224d26d7269b478052985afd85a1962aae2bae8fc7eadc20014a03c82f9131008f03ef6419a1312034dc353f4b77556e583a6d7776597af083b686f9949c9e3ea642ac52c052cff5e52be93fea40ea5cea5dea5eea5fea60ea61ea62ea63ea64ea65ea66ea67ea68ea69ea6aea6bea6cea6dea6eea6fea70ea45ef78f6d800c20b570f9a1cdb227635f14044411f44e34c2b6a7484468ed8a0afb397020b20cf7aee7b138de0c80ef4e71b1f25ae3cc43e1b5f3868cc69f377cd8d1cb0aeb1d6e858f241f943f96d0fb243ff754c8d33ae00d36adf5c05bb48c6692b88808fc902d2213498f69857f617ff4629f72919606690ca9e43a28bd3dbe603e9daf38e0d842ea5339241bc53db5bcd70d39485a2aba93cba86cdd7e1b8f11609832e42361c44e77f1d8458c1c8c81be632f49620f548d557e964b378a77b319e8bb113da32f439fc0335d46121a8ddb5adef9bf846155922612c7b3aff6f887ebbb490c0d6cf64d85c08620e901f4a2f8c5b2c64297d4e961cae1dbbf4bbc6ffaf1536263b451b8c14ad37ae73cdb7cdaafb7614c23198493b8bb198559f78a34eb931d492e17de209e706ea0bfe07004626cc268e39b167396a707ab27b8b95e9a049b102beb0e7e0eca042d248fb830a901ca184a3e9ab90ad94b4c2b735cdfdd97de203e2f6ecea0c9d1d412ee03e4b441e4aca6e746f3376c1831eb645b68fbf30c2e3d9ace228e4caef5b062a2e5e43a74cfd51f97bb980e991d89e27aa98aad6af83b6edeb4612c71f162c172c1035c440fa4c2c57115a586a64ae48c4ea621967db843e91549af19ba7fd4252185cdc5f5a76fa87888f4f94369bb1c222c38a10352b593af95c2685538a00b01ac218dba0dcfbe22af1defdbc10ea26b454075d97e9461fb473b673c69ee1bc9add6eff053a2d423d630677f587e4e30a2a876fb2a57bab26d8b1d9e9db41ea85f25d21be475c6cdaa966b015f19ef719160533d53f64619562c882334856676e8ed0a99cd45bdea4fcad01fb445457ef77228412907a9a5e13e7157b1b7c269455c656b18921c46fe5cef4e5fd63022b0671297c583f5bcf7ab082b2b75fba10ce5ae26914d51a7428ed2cef3ab2405852bc5b9e6fda6f9dcbe6cfe3d9182ed62eb83f8448ba4e03691069a26ad982f7af4db269b536fa1d02b20b5f1c402b386de486bcb5a3d01617aa24f83d2fb08fbd26ea1d44e566a1ccc8d6efe11bf12fb22a68db50566fb41bd01df41efc57faf010065f406973ac795e7de17eee829c8c9f9eaba30ca6b106e521c388dc94d0e5a5f52b1425437a0560521abb79f0ee4b" + + "bf79cca062ac2ed7f2dc96e5dbe9ebf3d72a43853cc0a4f5106904d718cb9fd4cd694c9eec98db9aa544047e7f86028d1796fc9e66cce7b65bcae86640d12534a735a83cb2430b88f7ed3808b8f7a434a96c0977239956e9fb7f75225c71ebb2efd5db221cf9771381c8e7c8f362a895a7af31b5d4c4d0f9f587f59595ddca640ca8c4acce8e0e96e0d2d0193d419785c361a400c5455bb012b2e8c042cb21cdb1cf0fd004e11df66df600959dd2a515fd225035066d7379a87d679982c3de452f866786678f11f14e997cdf17188777fca8a2bfb5c5f552319c68bfed40eee38b1194419da7b2b14be8c32dfa9b07dc8f06d3d314d4ed9ab5c21cc808fa8bfcd17507e1794c927672c9e3281c7f440145d3e0c194ae78068d06bc2f49e0291e92a857b672063b3d2e1f113882446974129e6010c28cba0b14aac4d4a5c2c302b489dea9bb573bbb7ca06be15e7854e44461c36e4a684930853a943d953d963d973d983d993d9a3d9e3da03da13da53da63da73da83daa3dac3dae3db93dbf3dc73dbd3b09ef90a842b72fc47b323d980cff2a7362742ddc0d58a8b986e350ab56b016b2fbd842b905b6bc75787af4c3568c31c0886995a670d7c4e23007a5c9697fd18f431fbfeb9705bf6d9f90ab90159116911c912591279129912b913091359138913a913d913f9148914e9151915d9162912aa22ba22ca22da22ea22fa230a231a232a233a234a235a236a237a238a239a23aa23ba23ca23da27fa4dba8dca8dda8dea8dfa8e0a8e1a8e2a8e3a8e4a8e5a8e6a8e7a8e8a8e9a8eaa8eba8eca8eda8eea868c4c8f9515cdf5e81053b2eef3612e3b5dc1be226f081f4e245c364c564778e17bae93672ced5ecfeece308747b7089abf93c2b002c6d3d3b40768237b7e8d06de6a6ce973083adb4b52adde35f038c4aa6a1925ea6bf87c6a0f3a7b2724daa51bf0f18cc1a299433c175eb90187e2eb3347968006dd288b633fe5f766c53ce19d96e2577529781e442ab5064682a9993dd3d5bf3cb3ccf03d7620d9350c769ef442778a597bad14fd435ebf728822c978fb29fdad423ebe137b2e7b48714c065fbfc092b5230ac6247ff5933e0a61b4e81f284fb20c801b6f9bb7e6c9d78c858cf836551b8927263a406ad08cca1d278072c3c42d954e868e822e36e21cb82338e2fb2cd1782bdec66d0142d38b046b146b246b346b446b546b646b746b846ba46bd46be46b047b147b247b447b847bb47c047de473e6339f90e483eb55520bf36b263446c0897dab279b94bf55f3cd33ef943ba5558667a6f7b6f7c6f7d6f7e6f7f6f806f816f826f836f846f856f866f876f886f896f8a6f8b6f8c6f8d6fac6f2877a07aa17aa27aa47aa57aa67aa87aa97aab7aac7aad7aae7aaf7ab07ab27ab47ab57abb7abc7abf7a347b47e67806575b8e7ed2a1cf04" + + "d742a633705a058183a19a071e8fa81ba8c774348ac3b4d00818002d4045676f9da8fbed24292529a22b089ef4f2396ab3359f9986aa23c22fe209eb8923a02a203ad646a85d6963089067c283dba3fe6d82b284579aa9477d66b1731574cac6e804a32bb84377fe4a038666356e1fd635438b654b68d77403895acf8021fa39cf4514eff8004b55900eab3317533c968e463763c79f5018b52fe4431dbebbfc7845a957729b4da6cac4930eba26fae043e5d10c0916ec3c4a575762de71aa74f18b8b9430bb35c6c93f7855545c135def7c6a9202c154c5d8d0f4d4529614f2531ea325c97a211d5514bf15e316d4df41eeca609ac80b3ad14f897a247fceada639ac3ca2e8373c7449df300157747b2628093fd754726847c912d8d8e3d20c6b5c8ea6d1dcfbeb643c67f0d24701de0bf5c22f45497b6ac4839eccaf366947ce061b6dd4eb1bf49837a9417861b26cd0ac28b781666589ceead8ef01087c7eb3a6e3c69ed8e6ea8f41f9dafcc1271521bb6acfc6a9eeb3bfffed472bd659e6a624ad481a6a8b95d79ea1402eb142f5be6621773bbe05cea3f145f93103a908701bd41e6a3b63d696ebf3f156ef79fbb008e00cb131b431b531b731b831b931bb31c131c231c631c931ce31d031d131d231d731d831db31de31df31173dbb941b955601b420d625d725d925da25db25dc25dd25de25df25e025e125e225e425eb250e260f2615261626192629263a753b753c753d753e753f7540754175427543754475457546754775487549754a754b754c754d75e3775dfe1cb341f57635dd83afe633f12b488f751d8d129a47cab0d3a7dd6341e666140e946283764587b2beebc3d3ec77287030fb45884e095cb7c21aec62133f46f08424a18ba40bad78d75a6c5b6c55ad31e8d50849113b1a1d1cdb1e82216d38847aef7e3cceec5d59b4c4df5f4c00569b6f8aa7f3e9bc9178b5b2e29b1e743113dcf4039e8beba1d6bdcbd721faf63b8c8fdbc496d4eeebd0126b4b9b6b5d710100990543ff582f8463cba13bd3eed54ef85f5179618fe27234b73e12530272f3a735a8e0d1b38cd898dbb7e7e3d3358c39e05c0d36563708574f98c1d40f364953f760f07818131dc052cb8a36713515659e707681c8931b0299c7afd454e0d5ef28f09bcc782aeb934aa5dfa61bcca9daeb259828733674aa1aaec2128959b37ef49c25af96845fa697042a05a30c9d197d2b7855e897d99d12e09ba55f5424650587afd1e3e13804de2d0b4ab4507bbe4cc04a5cfb3c1354f578f3a9cdc287c7363a2d3bf5470a4b94609700f740823abd90dba47a07c47d781e1c38e09505ad96b0bbb1784f9e5f8a7102c5212aaa7e1398ea4e9b67896e9fcaac1d022723bbd43739c690d00f07c20ddc41e4700bfad8248927c72af26de6890eae60022e0cf42f907213f1" + + "77f134fc5281168fa76175756b957fd5870374193caa11ceac4e12bf64c0aac29fc412cd7ad939ec3a0cc0446a46b55a68c25244ea5818119725353f6b48696e08d907f2ecfdee0fea1671199f1f8e21b5331c3af855917f65d54722e176a3d0ace497b4f4c34bcef0f484092939373f495a10abe6d926ea4b0d70a9ebbc2cc741d469e1f5ea475d538310af95be51ec454fab7179763382e99013b2e8d4f40fc65c12297547ec47946bf3ac9c4c566168900a95259b22a119a41ca421f997054910791d4aac6aac6bac6cac6eac6fac70ac71ac72ac73ac74ac75ac76ac77acb8acb9acbaacc0acc2acc3acc9acfde59802ec18871b4f788a950a6c98c2d8c3b7f6233ded6bd7a4d8a449a54ba54ca54da54fa553a556a55ba55da562a565a56aa56ca56fa570a571a572a574a580a5faa5cf20774bdfc62ac095308e7e70b1fee52cf12df9cc4c24601fc1c2cc1ee98f1341a18fe0fffa6c1771989a4d1155efe4acff30124837b870a77b3d470a6bc4fa9cc7922f0b3893ae99cc73fe490a4d1cc92015df0ce7b1f236f6c9fab4086910282da741488aa4c748d472e85948905d6bb93ec8e556ef5e9465e200955905707f807d4832a8d10d35a67cdbf2ac97c376d0cdde78fa512086bd0cfe74459c4e1649e68aa9c86a0d7e552a0438068c266dfb3118741890e3ea39fd114c8dbef0982834897796aa9dc5af70be83f8281d601ea422422d8178996622fd516da7cdf6febc447be382ff4f109636dd4c5d1a25560e5a5693d695499ba300849a0eb6cb225e4a8b4fe15c935fbc91b0a8edad0718441b7ed17cd6b5d9aa2f703ba742d167647c09dfba48686e8b705f80ac834099abae45d1e8d581d922ed7cf1b39bfd04c705f51ef61ef71ef81ef91e9027ab5bc3c331d353ec110c0a0f8f1ecaa6e9b813cb10d811f07c168d58848489b3170a161b5b3b1cb97be492f60cfc0dfc0efc16fc3efc40fc41fc42fc43fc44fc46fc47fc48fc49fc4afc4bfc4cfc4dfc4efc50fc333d353d363dcd3dce3dcf3dd03dd13dd23dd33dd43dd53dd63dd73dd83dd93dda3ddb3ddc3ddd3d77bb6d619261e0a5dcde58f71eec80de1400e017211805385d9a43bd1a460c6f839690e99de98f2b987c4c78bd833dc35e1e0e5fc6667cd1a3ed38f19ef9fa309436f97ecc9ac3bc21fa921425261a388d641e7578a401c7dcf30afe9e05fa25c8681991299baea9a6f033a0e4c3b4dbbae056e1630039714a6828e13bbaacd452d5d8d59bd625d8cad87cd986e0a1e1c63d87701881b683fca097a5e0bda0cc16ee70ef71ef72ef73ef74ef75ef77ef79ef7cef7fef80ef81ef82ef84ef85ef87ef89ef9defabefb3ef91f3b9fc5117871b49439f58935b9a5b9b5b9c5b9d5b9f5ba05ba25ba55ba85bad5baf5b225c245c255c425c445c665c6b5c805c227a87d7" + + "3616942cce41ac440259f059d562e984e5d3658dc5b582cffbd0c8e30501a10c1c7962c5b8ee9848034e044e054e064e074e084e094e0a4e0b4e0c4e0d4e0e4e0f4e104e114e124e134e174e1a4e1c4e8383a8a726d95cf1520ae887eb9d3cc497d43ad8626b1c954bbf2dd0e10fda2c614f2e5d4d6fbec101d5e524ff8e54afd53d395b5ea994e2143f68795981a5ccd3cd0fdacb187c22dc4bea681a9bc5cb14e691e8bcf3af123924e5683e7ae78f28e2e54562b50acf27234f3ee053d1867f9690ef0c22e671ac0fb00f60705b016d3fec4bcf6a45b288b888c70f314247e18a728dd8b03eb1a4b1d4b126b3ec09560d570d580d590d5a0d5b0d5c0d5d0d5e0d5f0d600d610d620d630d640d650d660d670d680d690d1b8dec96f596ff967497f897439802bebcbf5ec1b2c1d5c247c3f5c316c56fc5f4c561c6a8c6d9c694c7b2c768c873c821c936c9a9c9ccc961ca8dcaa5cab6ca33cb42cb5dcbfacb28cc48ccd1ccd6cce6ccf2cd60ce6cce72cea4ced9cfe9cff8cf3ad086d09ed0b3d0eed058d15ed167d195d19bd29cd2a1d2afd24bd35cd361d3b1d326d427d42ed46dd424d530d548d5c9d513d61bd624d66ad6e0d6e9d6f5d626d74bd84dd864d88cd8a5d9a9d9b0d9e7d96bda84da91daebda5adb63db6adb99dbf7db06dc07dc21dcb2dcccdcdfdc30ddbdddc3ddd1ddeadda4dec5ded1de41df9ddfe8df1de0ece1ede1f3e159e2a8e2b5e2e7e294e3a3e3c4e375e477e479e4a9e4d0e5dae5e1e510e673e678e69ae6e5e617e818e81fe820e83de83ee83be943e989e98fea90eaceead3eadaea76eb79eb98eb37ec3cec48ec96ec21ed27ed31ed8fed02ee08ee2aeeabee0def11ef1aef9def8ef097f0aaf013f16cf16ef178f191f10ff218f230f2eff2f1f2f7f218f3a4f3aaf3b2f346f41df521f529f577f50cf613f623f600f708f719f78bf7a3f8a7f8bbf887f992f99cf95dfa64fa75fa4bfb55fb79fb3bfc85fc8bfc99fc3ffd43fd67fdadfd0cfe31fe41fe6afee0ffe4fff3ff7300b800c000e8001902570258025c026d02e302f00204035b03d503de032304b804bc04e20491069906bf06f806fa06fe063a07c807d8070608c708e6085d098209ce099c0a140b560bf80b100c8f0ca10cd30c640f0510b310bc10cb10c212ce12f812f9130514d514f31458155a1561156a1671167e16de17f7170119ec19271c8e1e9d1e6a21c9223690b793c5b516dec3e0fee1fe821e9de4b4f76ff3a43b168b4331a97311bf282b2b402b1882c4a80baca6dde90dd82e0c6dc48b608c5a90fba16ebc62c7edd5532d115ad16279668595d4d3b1e7675b9a6296904a9edbba97f013aca514c244c97b9ce0f7240d506f50b573a975e67c5cd030fc740cd10d31213b464850127e33e61a7ef0916bbc57c16330c8aeac1d6a1f4f7f" + + "84a350a9e8f8edfc3706740d8532837d53a3f1c8f5e65c5ac971c67247b448b449b44ab44bb44cb44db44eb44fb450b451b452b453b454b455b456b457b458b459b45ab4756bf18bc9bd6ff81e087312184299cd03d2dad3aff8eb010208c1350d426b456c456d456e456f45704571457245734574457645784579457b457c459a459b459c459d459e4552b7e5a4c1ee8df804141815fb44b3bb77f7203930412b8bb69d3ae2fee29bf11503ef0be992792093231740546af3b299dd341530393c5d939023241f731f83b5fc0dfdcb0285320f56d9e92a08d327d3b4d64297e64cfe42d0b1e4ba0a3b0f6c29142f45357b7e56f5ea1ad3939195f9f4256f49fd53ff1501c415b41b5f26f12ce236377d5b8ff9956daec0b639be67ee6dc415ef9ef59a0c510e533220ac6fbe30f84030e7619c8b589ad8b88647a699dcc86047a120a9462fcfad0f773233404244578134a0c0a3c6a3c7a3c8a3c9a3caa3cba3cca3cda3cea3cfa3d0a3d1a3d2a3d3a3d4a3d7a3d8a3dba3e4a3e5a395add01d872e6273388daead2ac601dc983594738e7af67bbd814f9cfc9f55cccb50e08590b55ccb43d2bfdac0dac9de6b5e5cc20c193b215b72b4763e7bd7b21e12b7239236504069f3341a0e1cf01e422c422efe507d5618880e8eb9bfa6c223018664869ebeb04cbde2edf01a83382f5822759643ca4c2ec386ec5700b12e0e9c0d273b987daa1ab13dfb2003a90b844b1f4c3f4d6e51c472af73517a7ee40233064dee4f16583c64fb65a471899581e868f48af8e7111312e71da94b1c5b26cf05d05415532e70397741f85fb579bc7b55a815bc512c5e6dd78bfb8fa3b9b0d6b4e2f2ff5b098f0dc541b9573307b311a590379ad8dc09de48e89613091e4631f835093ace577773cc950d984f379067a7db9933c747675e205f598d038ee6bbfebcc4bdc0ece103410a47105816a51ad21e4932ac3ac070737353759f95aa97e49716995df93f41db4f698280a6f8b6dfc5d1c7fecbebd5aeddafdda4dffbe21bfa07fc10025c042e40964775490b53a453065fdc60ed72207c997f9f8290ae77af4eb1e8b1e9b1ddbc16c49ceb2cf8eb069f1e8345bc58d368e86f497b518c439df1bc43c5e0d3e1d31102000daa0d25305938584a946ca799fbbc1edf7be8e9108324ae440945d3803cc2f6c883c957ca3dd5cd014b0e320f6819522c7f30bf42f248a25322742682ee82b283fa83b691a3924693d1937496369a009d29a749a7f9ab68aceeb364b573b682b661b9b8bb88bfb0c2bdc513c83ecf26ebc5028c138b26b62fe93bea3bd33c5f4322471b4be24baf580e5b8768cb6bf59065c8deee97f6eefc270afa537a5f686fae8b2f8fef937dac80cf83db84db83ea68098416922b723ca949da71e076f7197b2c5059216d3c9cccc7da14a515161738191e4a" + + "78621968df771a83529628bd1be738ecc0094e32657226ab8fb539cbd6cedcd4a2de03169823e727992f0537a1376340ea4dcc52fe69f17f7583ce9319a2b7b844bd48bda5bda6bda7bda8bda9bdaabdabbdacbdafbdb0bdb2bdb3bdb7bdb8bdbcbdbdbdbfbdc1bdc2bdcdbda2f1f824624c575b4d6f8f717f75e07f959246b54a056c34ec417a44de76a989938ed8996df23f07fb2a5138354c174d7a571a5eab6629a02ba21eb564be51f4d808e57dcd978ca76bac04b697bb54c7abe295f05cf29efcf513e939953b2e3e02502c540a6b0b7214bbb2c4f8d3fffb0431693ac954ce5ea87a6c86b387a5946cc77ccb7fe0eb10bc5dab62df632b7c809fc2a493b7f9d8a8d95de834eae1fb2c067c38b140ea578d5caa5eec6ebdb76bc674cd3ae04ae4521a2e1fc522b22452257a2bbe35ae4a1464c18a7b9679abe4c353c5e4d331d87bdc19e538fa76fe98041027a72de9328e36043c77472b56c0577e58725a355f676c067351746377807b427eb397e3c66ecebad3eef24ef61a13ba25a630c93e7b7ec4b12d0b71149b1a431e7599e2af33b921d198d85707df163e1e4722c735fa4c2c576f65d0790194b297409e47a8a3c725caecfd3a176d2ca653f762da635e650c68136b82730191a9912d925e985a9a39de26ea140f4b204553185db06131a132a1e9a499ace3aee4ae9fb401b5d8db6dea3beede04f61af01b902f4b32f73822405a438156a47726791a8e25a2aea9bbaf97bfaeda1ee508e6781b112bac2b2b311246324b3c4f4a55b87b3e9d259f62ab37b6ffb7efd054d81bd9d4dbe4eba71153345038094d315dd9705b90759c23eda5f16b490f5a1d63ba6a936f8477dd7971b46cba58cabfd26edcace20fefff0745352b96e69e65a753b76155ae5fd66a0773be9c949d45a0afa2cda614a9aaaa46abb7adb8ad48bd89cf47e9feead1ec64ee49fafcff210550095f1ff839ce5558566680208b228b258b268b298b2b8b2f8b308b348b378b388b3a8b4e8b648b728b738b748b758b768b908b64a73db15ebbb8ddbbddefeaeff6e020c549c55bbd87d291709cddc9b1e569e770f02ff61ffdf51521b301c0f0e06be6da12a01373170c1aff1fe63c463d0a440d701b733f762f96e5b8cab939d5e1e121e82ceded10fa185672a8741cd6e6113a42874ff183cd98409c419c31a758aa9bb39cb3cabb87c688c689c68ac68bc68cc68ec690c691c692c693c694c695c696c697c698c699c69bc6a3c6a5c6ffccdacdd2cefed713f52ffbaa1a10259e28ee347e36584bf9624b760e77a0a46aad4bb9e9b987bef2c134edc7edc8ed60f65210e834cb358936ad5581563c679a692a735c99bc9c1eac14b8d1db89dc9fe3d1ff520c4728212b222b933e6040526f4aa68fcb6ada5df2f10ee3dce05be89942fddd02a117ec54a7633f73" + + "6e782b8bfd990ea293b16abdf4bd61bf7dc16ae111f70102a4034d09c0368d48254a2762b47554f121f57823ce47e174b8765a8a2dbe2bdb1f09690de719e232cf425a46924a144d225b4a640e69af69e2754d793d7f1490b8a3d733e1385939a698f7c22fc56c007f054506651bbd1e263361835b84ada68db2f0080c14f51f713a0649e54ce5870193ce9ddfa594b3aeb6ddbce4c04ef00bf33afb96fbb6063808bc15f91bc127163333404a532354dc5fa160fa62af63b5a85baa66ae0eb16eb703cbcad2abdb66dc00e7ce0858411e6c9f6dc19071d298db5ddfa61db3253f2c7c2fc1688e733b7ea8af5cbcafffd630b63acd45e658e95836617b68b6868092b0b859bf67c497d9d319eb377d3d0f4b9556a76af692e696bda97fd5b4038904e9459e4a8c549989798b658c5498cec736e1f84915542eb707ded9fe140a8112a023313c6b6e4d8078d208e10ae31be42ce548e60cfbfb28233035493649004a6d526156ef7be2cf12d7d4d745e1d6e272ee854d0b58056ba8e000e6ae030d13512e083bac47ec5608576f5a965da37c0f862d86e19a26d1fbde1afa8904cb0a810eb216b3164a1cb724d847a24c955c8c600a6b6f8f8297f2a186abaf253b5fdba701a8e4b06b32d63c8968db8a98a62fab73b152b701f9650c000ece40565d6561a6626764ab68a06e6786af8691b1e9b5f4cbf6cb42d41dd5d2de39eadc0d0024c326fd3921eb39ec91f3cdf65d16617450883c91cbd53f0845319459675e3a7e118457cde7ddb6df2ae9ec09e9267b36a24b1f5021617863b366fd6f857e788cc1bcf1cf89dacadacbdaccdacddacedacfdad0dad1dad2dad3dad4dad5dad6dad7dad8dad9dadadadbdadcdadddadeda8cde63e282f150f86638f043374e54577c5cb161ec65ce67b16c237a139110ac11ac12ac13ac14ac15ac16ac17ac18ac19ac1aac1bac1cac1dac1eac1fac20ac21ac22ac23ac1eb026b427b428b429b42ab42bb42cb42db42eb42fb430b431b432b433b434b435b436b437b438b439b446feb402f204ce347a39693c843f4942614563456c456d456f4570457e45884590459b459c45a545a645ac45b145b245b645ba45bd45ca45f06ba67d61ae73baf5bb9acdd8cd4ff328f490f65e163445306f96714978c991a3aa5eb1ddbb7bc1e3ce4ef40e0c4013791ede8c0fa441a689217b277b2e08388644d644d744dd44df44e044e144e444e544e644e744e944ea44eb44ed44ee44ef44f244f544f64404452347ef4c4581438eface52f88b015b027d392d5349715075328beaa3f6b20df1c85c6c6249784294f4a2bebb04c1c0d48edf81ec2af2180f1333cc38b63d6b474255946f10962aa36cadebcbabd971ffad190020a338c142d244b6484b7d80837ea697a80db2b9bdebc384c48ece98e030316e37663f18429860" + + "5b64df6a836c467c7b90a4a9fac542ccc3cf2edc8f15521e3e290c378e43554d3763d5f90d099616863d873d4841367ffd8bc895c995eca8c6a9e1b4bcf3c7ff0e00a9654f6d029225c35de1ef0d8412fe2a36396e489649a454c15ddb9975d58eeed3f6d0f7cd06310fbd17061b1821252ff0375b49df5d337339828f90ef9d2aa28fbc4acd4ccdefcdffd8a9db29dc37e8621db751bc63d882d88d19903892ce960aa4d8c427cde5d2e6d2eed28ddc77e8f8ea86ebd5332738274e555282547f5e1d75a6ae2dda55f01ef9bf0560184863c3e28af79f162920ac35ec4dca4f895b585d0c8a21a33cac6fbbd7be2bd7d5e383ede6ef9cff87038803371735189722402521296e458e66996e707f12811a96c5c2f9c2fac2fbc2fcc2fdc2fec200c301c302c303c304c305c306c308c30bc30ec30fc310c315c326c318c55fd2cedafdf7750a81115c170026f0263c330044ea4d5758ca7a257f2b81d684c48a65926da1f5a259a749aa89ab74b5e8bf6cc493d608eb5509f610ca1c793a234a5f4f6750b751cf7a5c7c55823a8cae9427abd8c725d52fe00ee8f8f4adf646fd6a022a0911153a28ba53ce560c5b0462c0687f6dec845e9b119d959d969d989d999d9a9d9b9d9c9d9d9d9e9d9f9da09da29da49da59da69da79dc59dc69dc79dc89d15b3d7d0ccde63f49425f2295a4855612f8fbbd078e26cee69faf110a7191b275850d558255c485cf85c8460d768d6748f7a118e679a179bc8a018d356ec34f5ff022707000aeb17c922c245764ebe55ee85df89c1b4c2ba51d2b6f4d40a6d0cf0141d17711e03598769e1cfb0378745265da3ac8ab56dbe12ca25caa9cf9cdb9ddf18f754ff7a209e3725385f394f3c8d3de243424cd258f65a238c759418a2fea2a0c395c9becfe7e814141514db1583167a17ed179e2baf2d5a49e176c6781d9520b724b77bbccedf34e8e64de84d6859075d4a70907200836998d299a3a006ad4bb829c4eec4bfd7b5e0b9ee9bf026f485fb2d008d0f941fb22aa931153c0f56c95bc95cc55fc85fe265b86722718e79e9824583899352945594959506a0dba25aa95ba96eac10b8f8cef1ddffe09be37ce4fee6fbe8b1e99df623f8d3fd9b0168026c0af72af033423b0c42c047d44d3b5241525d539a6df36e5675587dc583f6887bb75bedda029e173a34dc3a37407a5ab45bb55bf25da35f9c79cc8e7f91c094b4954797f2bad0d435dcede146f77620fa215b39b05dea63346ee2914e9443951fad44b1f8b80bcbbcd9c7d9cad9ccd9c1eefbf119f25dfb4b0b100cee14ba25842df32e5a435f432b442b482f4bca54225d74618b62bd69c770df72bb7b2a7dc584d093869a29a38bc1c1c691c894caa8cfd1d8b0e0b2e020e447e90616e41dc31edc25082b6338873c893c98423760d67eb582cd8c628eada1" + + "23a3f6adbfbb72ef5733d951396b5b78ff82baa5b9a735c737d601e57f11342c4a2c165a24600d640b7cf47db37e7a7fcd8693880295aca86cad8fc412d359d8f8dd62e213e771f0aa0f35162c214f3ee75b536359690c6b54788885339dd0c2bccfb3d11ed3a0ec0bf144fa7c05c30df617352410311131373ca142845802697f726777cd82ce82cf82448edb8efd9a7fa093a3bca3bebca7c6c6cbd4cf60d783e40ae894f6d8f9d3fb23fd00fe01fe02fe03fe04fe05fe06fe07fe08fe09fe0afe0bfe0cfe0dfe0efe0ffe10fe11fe12fe15feee04031005253b25f8277c2dc52f8e3c3643cd49056bac6b4a6f1274b9745d7a267f178b188b1d95b69c7f9f40a15ca3f7b198b539b9c1b9e2ba8bbc8ebc8fbc91bc92bc97bc98bc9abc9ebca0bca2bca4bca5bca6bca7bca8bcaabcacbcb5bcccbc19cbd2d6a7d7eadce1df97e442e9f6feb204cc1b39240327e93ffa456658525a7c5b6f5f076df375cd7ca79a5abba3beeac237c7bdcdd2ce4ce04de0b1e97ef0061a973b913e1a481c69f98565a49cc317ccc5def7f9e2fe372f383e8f57645b9b662b6f8d80858c789607a277a4aea640b491b41aba4fc5d3c58acddad2f2e3e30b0b0e551bb33466530f59fb62c266776faa7cb2915c945898229d1fa196b1d5b40bb741b7b1ccb5ccf7d03d044c299f3b443e6144946d61ad9dd5efdb82df29ea9f01c52fce5301763377b178bf81fab94cccdcd6ceeea2f1e1055b09ff121f558d56b057f76d747110727283f0863296c1a238a5e8cd41e7c6e919eea3f693034c216b2bd53ab754bf560b6fce7576872b952b96049c7ca098df25e1bbe1f4edf8ed63eff2f81b08e709cf3ab73b514ba35ba55dd07ce58e3f94b5ca2acb06d4e4d66ae0c2e21be353e57ee91eeec0ee8def56f036f188f362f8e2fb5d0e5e0ee30f63157a167f1671231f296d2b6e343039ef39b43a4f3b323c47440e458e53a15b2866966a176ca4708e78c28cbf91939551b4c3b704bfa4c6acc7bdda08db0ee26d1e0e548056a25be36c516f109334a5daabddbae6baabe512eeb4ef5e058b0b352aac2e77455583958438a491b90ec544c67dcc6c03dc0ba626f52a1e3b4544834cb850046b1471d8759d7a457c699f14a06ba4d0b119e8b6fa11194e23482a6c304a3aa73ef346a949a556db56965aac5a696a6a6a106b9a707372bb85faa641a766af40b851c296c23ed14aee4cf7b206780f3e100a1b702a032b542c042df03472365137b839be3fec560b7e16b0b0b96fc864d2c2d2acf39c0f02345f72008faf903d9b899c1eafea0e4a12cc1d7b36323c83445547c257ae5c895e9e5ff466617c7286548cad8eca8e4290dd91fe95c29de5aaf0ab62b031c021ca91cce0d2f3d3cfd5d1dbb7dc45eabfed60eef7f396f8690391092c10741e7b2099576158db5add5a" + + "596470668669167bb57bb67b1b85218e448e4d9f86a4d4a787a85fa916aa8fac40b8b1c499c557cd5cd02fd589e4bae9faee0bf0850eeb207a2a5033844ae84e3c509d5b446bac6dd96fae7770783d7f8c8d428eba97d59af8a7ebb20dbf3bc499c970dd99e999f4c524cb3b1a491b490e5b1c6464685d74708c56a5d6b8eecb0fe5f6ea3df028f4fdfa102f5833e739283b843b7b426b469650a985b7970fba00bfafc384c5e0c86ed1f1d3add43fda89e720e8c7e85bec32eeca07c00db21c3d1ef126e33fd04dd865e1671c6db285d19991a7f2b7e8c0fc053c4e3e4ef44eb55ab5631868a77bcc88809df4ad7aaf2fb3dbbd50c0a8e4f8067f090d1d7448e14ae763157a8a7a2982eb848a8cb98d6a95a098bebd94cb24d631f836016919101aaf1f7b2d6c47ba4a1a6c79779f786bab36c73ed7ced9eedb19df52e765f1e3f50af7aefcc10d740e98119e118f15861ee62154245f2ff4372e3ae03d5d46ec47f44b6c5f1767446a4c6be76fc670b473ae78787a1a7d5d7edd9774af04b794ba3dbf43c591c74ad203e8c3f0c0f1daf95f059c0a89109b15e61c3827bf3d7e4f3d67bd69926da179838098811d89438bfb8e93957aa8feaca5c28ac520cec3d2c5d29ae2dee7bfe97ef0fdf115050413cb14fa162725f54b354daf4da568786c41746576eb8306860e8bf6b323d9badde2de78e197e285eecff5e8f6e9f60cfcae0f5f16fe248036504c818355a0afb1b4ba07bb9ecd45eba5ee82fee6011d13de2e044c894f8450b35a2283e68711a2a5a476c8b3012b03ff3cfb434499cf9abaa63fa720bfecc3bac66ecf8fd051d264da48db5ee515ece5feb0231e2ed14788523959c95dd36fd5756f7b858137a238ac52aee3afbec19bd469d847ebdbebaa16271d6a52bf57fd852a8cddacdeac81afa0b037b20db548c28ad6cde0dfe9a90d191ef52081304f340935c9357f37f83a92749a7e048a4e90f59010a03aa259a437c4b9c59526a43049418b437c59a25a9a5f0a64f56534706776f77fc5812088d1a4e2b574c2c8c298c511d054d2b0d8b2d83be5fe0f782e6a6c3570da9e1eaabeb6bcca70cbd4d66aee61f8c6fe9a009401470ff218d81a6b1b8a26732c7133a3385364d96736695b70598869909aa616a951ac7ab423b6d2bad1cad5cdd6cdb2ceb3ceb4ceb5ceb6ceb7ceb8ceb9cebacebbcebccebdcebecebfcec0cec1cec2cec3cec5cec6ce61d2e1d57fd6daf41bfadd05b1204a2e0c34e14a765081581a6f2472c879c979fa85768eed93d1986699679965c367c3ecc423c92bd4cad597d6d5eb5cec29f497f74ef904fb4dffed05ee05df07731675187a19261bba1e5321083105585c5c96689768056f127e5285c889a08ad099b5a205b870bc74dc78dd79dd7add7bdd7cdd7ddd7edd7fdd80dd81dd82dd83dd84dd85dd" + + "86dd87dd88dd89dd8add8bddb9e1c6e3c7e3c8e3c9e3cae3cbe3cce3cde3cee3cfe3d0e3d1e3d2e3d3e3d4e3d5e3d6e3d7e3d8e3d9e3d2e6d3e6d4e6d5e6d6e6d7e6d8e6d9e6dae6dbe6dce6dde6dee6dfe6e0e6e1e6e2e6e3e6e4e6e5e6d8eb29ec2aec2bec2cec2dec2eec2fec30ec31ec32ec33ec34ec35ec36ec37ec57ec58ec59ec5aec5bece1efe2efe3efe5efe6efe7efe8efe9efeaefebefecefedefeeefefeff1eff2eff3eff4eff5eff8ef51f552f553f554f555f556f557f558f559f55af55bf55cf55df55ef55ff560f561f562f563f564f5e90c8129f536c857015b8fb86bd0ecd2a6dbc6e413fbbefcebfec8ff390e2714c01453229d2c4830f4332d34f83d0967ec801284b786d5bdfaccafce64d082e797fb9bfd5a1da629d0392744dc5a1a622f81db8bb88c6c93f994219623964797889feba01ca331a524a89cbba5c9a9c94cd2c0d38be23df3cff665fa78073f0f8d2dd82efa344d351a53b854ba56a96039652b67d5732674e276bf7a038b9f8dbfa137bae6d7abda7ae80efa3cfb96086e097e123e2709281c2ccc47184e92560f5a825f857a3c8e51dcacedcf1c7043ee432645ac50535261561557b057a65a585e5779487a3b7b257ccd81fc839496c59fcda206add4b177b2f7b8ccc837d9d8edc8fc34150617a82a7b3201351b41dd446e4a136364686668876b3c6fec74ed742984f48d369624b219b3b9b4dbb78db98bbd38ccd9eb56fd8aff5900f40f8c33277db488349141a742a75ac699d52bd6ffdad5dd4cdf1fe16b06c1095b0d5c0dd612d8121a1bd8275931de343f38ee3d1a3e83553356326464e702ed7af14af2f0052f26312657296f350b37923c293ea9444c4809707b77cc850d93549544c342cd81f4a810d61863245330843a533bef51fb5c5278257926790084888f0d95d499d79cefaf03bfd2d05cf5af08aa1b49311d38004704478f50808cbb9d07aa00af23c1e2c3ccc731d7c7dca0dd40e3b9e8afee12feac23ef2528424a5f0460e1648666496e0f8dd990969441b980bd63beece104e766fc0c05b5098e0a240b270b6b103f1f70249e2f2b3304341453e759c067b568a06c4173d7777584fc8b748f3396c0a05ba170a777b2d2bc42c3abc526ca73d367d93be6dbe7f8e970ef21f0dff0bdf12dfc33fc8117872b3233c33a073ece46e34fd253d35f89660c74f074487b0e7caf7eae80f483a488c8898995419726a514b1bab5c7c498cc72d9cddd8be867e968e951f5f1f658fc88256739fd39d13f87416c54a8578f585462426a0679f479e07bae7d5a7f1c877187e99793a8c0b3c1b3d3bcabc70de3e2e3b9e467eb8cf457fbd909980b4b0cb10d490fc10fc20fc30fc40fc50fc60fc70fc80fc90fca0fcb0fcc0fcd0fce0fcf0fd00fd10fd40fd60fd90fd11240149e1a4c1b2b1c7d20" + + "e52d443ef843964783488c4fd356f75eb65faa724e77137bd48802949ea55ca74bae94b0c4bbdebd81c0d6ca89cbf6ccf1d750ec24ee47f2bd0a8442a852aeb073c5fbcebdeaa1ffe406381a8e231f25432b6b33ff3cfd411343cd49df52307115774c7bdf7d778057855a855b855c855d855e855f8560856185628563856485658566856785688569856a856b856c856d85d385e2882391ee93f09397942e9d329dd49d81a4c9ca43cd0dd7f2000d0ac50ff31816233538ac47525c256f7276598a7dabfaac01aeb8bf15c8b1ca2fcc5fe8f6eecdefe4f381f7f602f70b0c192f1b6e2b6f2b0b50ea60626339690c75067e3581f787d48cae97efa046a1cda766a877aa60babbbbbbc3f9c561c99fcb08cee2dc74e0dce29bfdaf1d942a912e4d3d5048d4520d57d057eb5ecd6b226eea703271e973a87d4086118a128a138a1a8a9b8e5d8f01947ca3e2ab10b059b1e7b2e9b96dbc62bf83dc50e8ecedcdf1bff2d5f5bbfa77fd8aff72037303c618c718ec20ed2095359735223ba84067435a660b6dae6e71780a790b795583bb89bc89c7893c91cb91ed968d99c1a1c3a181aa82aa79b58ebccec4e5efa1f6ddf84efe17023406f3067e073509920b930b38127219ef1ec4281730c03cef415652835a9a5d475f7261f074367ba37ddd7f91809380e193e39301abaeaedfb484b786b7a7b9c8bab0c439c625c7c7cbe2cec5d1add266d7abdd02df05e954e9e4ea90edb8f8e1fad6fddb02180a110d130d55106011b228812f5b35d837953b3643684862528d55a157245d8c6021640c68db687d69ec6aed6a206de86d0f708d7003741a764177e777e8778f78cc7c0882da82e783e7855d908f9785bfabc4e3c610d0bdd446d7fcda71e0cfe74fed25f693f74a0a8534d63a1b4b0c4cd15247999b99d2ac80b2b5b425c098ed9cf5460e821f0c264d2e4e2e502e76327b32f732fa320b4d114f124f02520352915299526f57f95a015b035b045ba75c625f17664b6b9a6c857141775f786078ed79e27a137b727d017f3e802785cb85cd85d38504872889b98e578f1492bc932d99ed9d16a02fa2f8a89aa910aba7bc7cbee9c684d810eb8df0d4f539fb57029704f20674281c2f65315e3af73ddd47ad4eaf4ef85b32603760d16222678f716389448f9292ed9e78a5a4a637beddc111c91fcaf9e27fe94ef31ffe4affab11012e85313d3448367a3dd23ef243f0477d4a47514a51f7535f566559db6a3e73f5880c8cd68e86902895d7ad45b5febe5ff3b6f390085e3e114f81576161c762ae6ed3764a78bf8163862a95db974b9a9aa117a685a931aff2af0fb517ba01c529c7f9d0fad021d7d4d8d6d840dd60dee6ea3cf061fed7033506cd097811791174137d22113d904ad04b9355655c06600760e068886dee71ad7cd2846088b08a388ec68f" + + "51a36fadf5aefbae4ab3beb5fcb9ddba3ec046c3c4c629caeacca2d9a3d9c6dcaddda3e1fde58deacffafc0d031c2837c43906410a55a656a05aa15a9964c769a07748841985b185c18a588c5b8c0798f19e62a6bea6f9a6dca7ecb1f1c22dea9cfea6ffc3067d1bad35f9373c451752505ba35de96efe7652961898ea99dc9fb5aa0dabbcab52b02db798b87bc77fc73dcb8bcf2cd01cd826d962eb46ef32f0f9f044016322aa248033d234c536033a52521b55ee5fa962a878ad7ddc7ebe8208851b897d963c98f59ef79e0fa211a213a215a216a217a224a25fa261a262a264a265a266a267a26aa26ba26ca26ea273a275a276a20ea328c269c3ffd558ef53f426023014631a0828ef2fae30373173433c452e50a050f45bc962bb6946764f782f81b5821583a984958b1c908d923493e199dd9c089eae9f5fa047ac6ab26bb26fb21db3c7b65cbb93c3b5cabeccbfccddcd3fd2e1d925db6ce700e826ebbcf698f872f976fb30000a05dc05f10a010c2011df11d8142916a1213d22272bd02ed22e4235103b7743d34519481e4824480f4a13528e528f5292524955dd57335b345b985f995f9a5f9b5f9d5f9e5f9f5fa05fa55fa65fa75fa85faa5fab5fac5fae5faf5fb85fbb5fc15fc161226481666168856e3072d67375747a747b742575ce795e7b4487b48913923895509eeea5d6acd9acc2ad71b711c48bcd70ce39cf0ae00be09ae508e73aea37ec1eeef3f571f9e20a520fe41647191627e627ea2bd82db63287372c386b426d4213521d531e534557df59595ee265ea69ac72f97df489d98ca390ec90ee90d9916595a497f0996c9ddda006a25aa35ba354a814ae63b267b2dbb39bbe8ac90bced0cec7d3b3d7cddaabdf46e1a9e1f7e6fde745e87aeb75ec80f1dcf3b9f780f86af9fd064b091e0ce60de80f101426183e28802a0b2d98334f40d948914d9053055a5965406cb86e717249732178967cb97d827fb67f1a9238a178a527b52ab523c896ce2dd3ccd415d899e271e413e9fee988f793040a0f0917d619731bb11fc924dd29b62a6f457848b5511b54185aee5d356beb6ea379e182e383fe8deb94f7941396f79bb99cbaaceeae80afafb8a8bba9bbe5c985cedcd1a1d243d900e91bee1eeef3031406580672069207e30cdd0d87107511121206177919921b8e1d4b2180229e23a924ad2a0131f9314233f536c03757380639ff39023b043bc03b593e27429d469849754fcd55f656fd58ff58675fbe5f5860d4601f6d4e6ef96ff8730481e1833586ef8b808c5a8d8090d9900692fb99bb9bce9cd29cae9eaf9e67a3aea36ca471a8caacf4acf8b065b4d2b6d3b6a1b7bcbab0bb08bcf6c877cbe9d348d8add81fe134e469e6bbebd7ec14f23ef7d30ae30d88113a15da1bb22525260d2d542e7842bc43264680475248e24e" + + "2b57fe6241651866b66b0f6c826dcd788a79207b817dd97d8b7e1683d084da88428aad90bf91c9912a987698fa9ada9dada1faa275a5c4ad17b166bc1fc052c081c643d5d9d84adcd3dec4e014e842ef96f5bffce5147c167e1a8a248b24312fa430a936a03af73e4a4080434c4a184c34503e58f958085afb5ed460076e396edf6e827be889ea89868a00913499629d1fa101a2e5a2b9a3dda518a86ebaafc4dec9a8ccaacc4acd99cf24d0aad116d287d3f1d45fdc4eecfeec8ef084fad2fa86fc2000bb0356059c06b106dd07c309fd092e0a360c540f0b141f14c41a03239a249d2b232d44344f3511397f3b9d417643e2467449265266588b59185b5b5cb75d6f6132623664976b4f74027e388218837186a18e689049927593e994209723ad86addcb2a6b61db856bc84bc85bc75bd4cc891c8cccae6ce7dd6d4db48de6ae46ee639f056f143f823fdbefd0a0088073f080f0d9a0d9b0d211d7f1f801f91227e25de27502e7039fe45ff45544f7a50d55cb25d285ec2625a640368a46c897208753a7be57ee77e6584bb86bd8a9b8d9c8d888f898f7c960d99ed99109b5d9df9a0fdb344b92ac2ddd322d632e0b7e5e9ecb1ed4ef8f5fd19fe1afe6f03af090e0cb80c630dde0de00f9a117a18c41b601c611c191f1a1f3522e626f1277b28ae2e9e30e6316c35ca39483a2b3ee13ecc40aa47234a3f4dad4dac4f99506c5960626c696d696e69786a00700b780d789878d17bfc7c8d7d457ed37eed80a081948216834a832091e4935d9eb0a267a87aa87ba834af6eb023b3e1b700cf3ed03fd0d2d280d4ddd818dbe8dcc3e1eae15ef07cf216ff0805331289155f38883a0b3eca44e148474a1a51df56715f73622366b166f6694f6ec772fd7552775677c37c7d804885c087c2874389ac95b29ec5a605a8c0a903ad0cb238b7ceb8c5ce2ed8b5dbb6dbb7dbb9db6ee657e874e861e97af6a0f781f882f883f8e9f9eaf96afa390004017e027f025e03870465056f06c1071409a709a809a909390b411279140515c01523172417301fb12621281b3347365b37873775400949b84a9c55ac58ca683f6fa5706a711473db746e783d796c7e337ff480b482558e578e7b8fbe91fc9164931394c594f29af99baf9dd29f52a0b0ad2db385b520b6f3b814ba7dbd0fbeb0c49ccf49d1a2d27cd38ad9210fd924f32ce53fad56235b825c985e1a655367f967b769846af86d026f1e728f7d9f8558866c886d88998a0f8bd092e6932f99d19b1e9e13a0bea23ba50ca616b29cb444b611ba7ec482c483c425c5e5c631c9f7cd47d4b6d59dd79ed7bcd8d9d865dc6de0dee093e394e305e992eb1cf5dbf7dbfaa0ff30026707210f05160d185d19fb309132833d843d4d41ed411e447d51a6600769696d9e6efd70b77afe8263957699aa9a709c17a1b8a3" + + "3ca612ae3cb37ed46de031e339e5c8f89df968fefafeb000730177038d08fa1237187219903c0d4e5f54d064c46689693a6cc275c4757d7c7c816a8fc5985b9aa3b20cb7d2b8f9bd60c161c1b8c6b9c66bc8e3ceb4db15dc76f278fcadfe64009802f7053b089515bd158716f61caa1fea22e62d195c0f69bc793b878d970599c29a8e9fc3a42ea8fab306b875bb3abcb5cbf8d387e75af010f211f24afff50dbe103812db12cb18d31c8a21ed245a2a9030b535673ad352d452f75d2a6c53723374467476749177cf7b1f82b9853e87ec8b2b93a498829e13a3fdaaffac28b11fd38ed78fd714dafadb7bdd99e24be514f131f332f3cbf357f68cf7e5f8cef974ff3e01e6017f0256069707f50ac40bfa0efb0ea40f3a1068116911cf14d0145a19da1b711d721d10208b21532a9b2db22f3b31a93346344438d83d0a3e5c3e273f88436d45c249c449ef4a044b8e4bbc518853895322570a594963286a8a74ef895d8c77ad82bc1ec2d9c41fce94d813e29ee479e6e0f8401e8b22c72a492c7d31c4337939dc3a1b3de745725130531e56fd579158a870c77ed6873e8c7ca00ea58da824adf2b85ad236d9b5d98fdbfbead1ebd2eb87f63a019d029d047d13911fad201e2b5d33243796403945dd45414a5a4de7543456a856f85acf5cd05cd25cd35cd65cd85cd95cda5c645e865f875f885f895f8a5f8b5f8c5f8d5f8e5f8f5f905f915f925f935f945f955f965f985f9a5fc55f3661a7643e749f74a278ba7b817f088ef0938f948c96b09b7ba0fbb009bdd4bd22c1a5c2c2c9afcafcdadcdb3fddbcde66e002e3c4e9d2f440f60efe670726188829222fd22f1c32ee3558361839763abf3db73f49407b59a85c7561f268827da6868987048dca94cb94cc94cd94ce94cf94d094d194d294d394d494d594d694d794d894d994da94db94dc94dd943b97cb99cd99ce99cf99d099d199d299d399d499d599d699d799d899e999779a789a799a7a9a7b9a7c9a7d9a0ea60fa610a6a7a6a8a6a9a6aaa6aba6aca6ada6aea6afa6b0a6b1a6b2a6b3a6b4a6b5a6b6a6b7a6b0a9fba9fca9fda9fea9ffa900aa01aa02aa03aa04aa05aa06aa07aa08aa09aa0aaa0baa0caa0daa0eaacbacccaccdacceaccfacd0acd1acd3acd4acd5acd6ac1bad1cad1dad1ead1fad20ad21ad22ad23adbab1bbb1bcb1bdb1beb1bfb1c0b1c1b1c2b1c3b1c4b1c5b1c6b1c7b1c8b1c9b1cab1cbb1ccb1cdb1bdb6beb6bfb6c0b6c1b6c2b6c3b6c4b6c5b6c6b6c7b6c8b6c9b6cab6cbb6ccb6ceb6cfb6d0b6d1b67cb9c8b9c9b9cab9cbb9ccb9cdb9ceb9cfb9d0b9d1b9d2b9d3b9d4b9d5b9d6b9d7b9d8b9d9b9dab9dbb917bc19bc1abc1bbc1cbc1dbc1ebc1fbc20bc21bc22bc23bc24bc25bc26bc27bc28bc29bc2abc2bbcaabcd0be12bf13bf14bf15bf16bf17bf18bf19bf" + + "1abf1bbf1cbf1dbf1ebf1fbf20bf21bf22bf23bf24bf25bfd5c14cc4f3c43ee00ce1d2e59ee687e7abedaced80f4b5fe15062b20c220273d65405547d14b33617476bb7c627e0a7fb881da97f4a8f5a8c1b5b9c10ec2fbc3aac5b2d50fd70fdc99eb3aeecff2e6083b0afe180019ed1e1e22c7231426af27682af82d7e3e18510053a3598f5caa6ed86f7c75b083968d56aa8fb29ac4bdcbbbcd68d0afdab9dbdff9330a8a1c391e04208a20f43a153f59502d525453a6546855a65fab67886e3e745f85e695be96ff9f6aa715a8d4adbeb199b421c433d666e3edfbca13cf18d81cd235fc3cfd493c4b2e4d644eb556065f0061c963bc65c768c868556ad76cf76d6b77a77d317fc783c8838391bf98cba583a9d1ac67afdeb054b77cbce8c9e9c952d1f9e5a3e679f15bf5cbfd05ff94ffb016b116381def206e231c27bc2cb72e7533bb357e36ff50af718277497a517d6c84ce8d728f039cddc1ecc79ed441dacfdb3fe065e734e862ec78081c194926753e9c3f72400c4a0d4a534cb255ca57925ccb6ed6776d7ac6827487f0983bb213cb6dcf17d9bde9f90fd418001bcf229c27632f732f83398b4a3e4cac534976de826b9850a6a5a85fb690beaae720ebd70c3512b71a941d291f5b213a35444b61508b5ebb5f989747ab70cc0af576f66700512eaf2eb332ed345636c7371d3f4f493b4f06530c546799e19dcea897a97bac8db22db8c3c1a6c751d252d2afd2acdcd6dcdfe912fa14fa4308ff14312cdd31a636a736a9363037a13a9f3df744c64758481e4dba508c51605d115e5076d67bb09d63a3e4a33eaf04b57eb7febf2dd4bede5106611d732b752b362d652e313070325c39904ae2553e5cf55fae6cb7776978eb8e4b959cbd23c8c5e57de73efb590dec14ba2b233ad543b44ef662c48e3ca0e2a3a7be13bfaecb45d57cd732e302f2d1f82bfb5b0864179f1b3e1cd821a2297e2eef3096375639cf3ec43fa5402646b8510a5a3e6170640f65cb686f699e6b2d6c2e6c0a6dba6dbb6d9b7bbf7b598d72a651ac2cb491bb6dc06ec082ca99d09ad0e6d2d9da7cdd79de9be938eb01ede0edaeeeb4f18ff564f611fcd8057408260ce90c321099139c13181dbe1f8024e627ef28842d394194452d4ab24f57555855e0591d5c1e5caa6bc5870a8edd944c96fe9dbda3e9b193d3abdad0e251091b0ce80eee12e313b9177820c72de2385342dd4b0d4f05557c7b3a8d14999ab4afbc47bdb2cac9d5b6db97e0f8e796e984ec6ef014f6dcf68af77bfb2cfce4fc62ff5b00b7017a027b02c630843b6d411d45d350495a46699e868790ea9cbaa46fa953ac5cc8a9ca16d5c4dfa9e296e7cdfd3d000a10d21aa01fff4243454545fe4c0e571357095bf15c975dd260b261de72228e8c96f999e19ae29a339e349eb59e4a9f8fa10ca40fa4" + + "08cb1dd926de27de28de2bde7de000f1f80a4b0c3215471fca368b49d3513e67cd8d8c8e6e99709979a26eafc2cd4bd63bdfb4df5ce159e2b1e3e5e525eac9ecf8eec7efc8efc9efcaefcbefccefcdefceefcfefd0efd1efd2efd3efd4efd5efd6efd7efd8efd9efdaeffff0a5f1e0f31af5d9f50507e616e9252927df41774d5056c6621a66a56d6d706e70af84e789c28e6d938d9b77a24ea6faa617a7c4a9c9a9caa9d8b305b6c4ba3bbf12c067c13bc6d7c609cd9cd141d274d9f6d9e8de7fe110e26ae62de9b5eab9ec19fbfcfca0fee5016e034609300c621725181d2ae52de12ee03df44a4f573b6ea08908935fa17fb61ebba2cf49dc66e3e5e40feee2f91d068d0b011b761fa321e724a5288b2c33334833a939023c67410b45314ea851c558215b245bd25b545db260c5621866226957694572e77d088d6d8e34a5d4a907b121ba34bd08c1aac4fedb27dfece5f2e5f5e522e94eed4fedc7edf0f0b2f5ccfa0bfc2cfd3e033805ee07ef07c40b1c10e2105c12c11b8026d5307134643e8e55b3612968016ff373157e2281e58b428dd797a2abc1b7dab770c071c0ddca61cc46d2bdd610d89ad836dd1de11ae703ecc6f38e0005049b0dda113912c81b6d2153238d282b2cb2328933d540dc421955f555e85603589a65ac68fd68eb6def732074827bd38a9a8d199a87a3d0b4b7beb1c3f6c747cc49cc77d890d82bdd1bebd6ee41f768fd69fd8f00ed025505660baa178918c11b18216a42ee57345a0961e56ce075e1756f841d85118778870797d697d399219beb9ccba67ab15fb343ba3ac016c481cd82cd7dce7ece21d822d8badef7dfcfe530e6e4e64de8ece981ecc7edc8edc5f06af785f91106130d1618611d1a20be280f2d63341b361c36b7367e37e039ac3a263c103ec641b043b7443a4ab058c763a064f66e347035704274c8743781d4819c8a3294eb96159b499c4a9c6ba73db738bfc7c03dc2b7cee0d044d7f6d793d870db75e900ed8afed6013607150db2131420e0200f249b33504551455f4e5458d55e375f3b60bf75fe76e577997e358caa8e9499589a699d8ea577aaf4ac31be97c054d175d41ad835d89ad85fd934dde1de9de192e998efdff10ff3d9fb3f1e43301343f846d5497755d0568a5d226761678e6e9d70aa7b017db787e3957c99b19f78a3caa685a700a88ba9abac65b566b54bc0b6cfd4d3d3ded4ecfaedc6fc92169316991ac11a6b284e377f409c4063422c4592482a4d0358395a475e4e660f68b968ba683c6abd81c296ffbf87db32dd21e931218131124a134a144a4f4f20557556aa654470aa7a67971e9a1f9abaa986b0cbbf77cb02d40ad583d6f0dc3ce621e822e831ee9dff2101e9018704880464074108040c7418b81f6b272829b93f6a4330445046234b784cf463757c4e83d584028b" + + "7597e79d91a624bd5bd878dfbde1fce4dfe587ec8bec36f0bbf82bfbf7fbc1fe0d03170413067707423b0d514e656c69ad6a7570e39a7f9c85ae28b229b22ab22bb22cb22db22eb22fb230b231b232b233b234b235b236b23fb242b244b245b252b29bbe9dbe6cc8e7cfd7d9dddfbae02de28dece1edccf29ff44df7c7fc6dfd7503600429061108780e4d12dc135219781bfc28fd281c379e461c48784d1e5ac05cda63d965808c628f668ff091f19100941aa71ca75cb798b9c0c054c759cd5acdded362d6add6c6d72ada6ce8b3ef60f161f10ff6cbf670ff4d0bc70f9726902cf5406a4bd855925a5f5e886247646d705c755578e38bdd95ffabf3ad30aefcd491e86eec35f1bcf55cf9e0fa27ff2700b20da71260193d391245ce45964abd52665544596459b562b7678768b36c6d78987bad7bb17bb27b477d59947a98c8a3a9ae0db248b99abe4de565e860f66df98bf929fa68fb6d082816c917ca178e1cb42c1236e438ad3ad945b8468b498c499a4ae755405faf7377764579e6899a98c29d4ba7b3c1f2c6adc943d4b3d454dd4dedd4efc6f1d1fb43ffd900d225372c612d1e43d545fc4e7355b95ca55d9c609f62ea66476b486b3c6e366f6f7257744475bd77257caa7d119a739e4da34fa3f2abf3ab85ad76d31aef45fbd8fbd9fb0d04f00879090d0b1e34bf50cd51cf522756ad668b685e745f74fb751879dc79ee79ef79f079f179f279f379f479f579f679f879f979fa79fb79fc79fd79fe79ff79007a017a027abd7a9b7e9784cd89ca8c5890e398689a699a13a465a866a86aa98ac3d9c7e0cecae88af265f317f65601f40b4c1f7f34ef3d0942a0451f4bd6843d8c8b9847b492b717cd62d11fd914e25aea2ef16ff59a0ce72f7b35a0369c446647534aef4a524d84503252c352b3621574347f1392019734a156b15ab12ab96cba0fd847dedbe1dce117e318e326e408fb8902e620f630f730f830d1457e46d54c885f936ffc809f83788b7a8c168def8ef693f6944296b2987c9c7d9c709ec9a22ea3ffa8a1a916ab8cb53cb6b4c7cdcaaadde1e44beadbf45ff523f69efa9ffa93fce4fe2302590327052b052508aa084809030c980c7811fd1b8d1de61d251f6a20ee27c02db631c73470377137f73953421e4ee45ab85baa6055720e7927886d8c508f889201a003a057ad5bade7ad36b5fdbc1ccf2ad8b9e71bee81fee025bc292b2a22324a33a834c13a303f323fcc3f3143e7461c4b734e744ec454c554c95401584f5b975cd85cb15db25dba5d7a5f7b5f8d628e629568a56b68713672c072d979427cf77cb7836784e8861c8b738f3f915893ea939694d0986599e59937a938a903ab47ac67afcbb1dcbf56c0aec05ed658d8a1da87dbb1de19e0b9e058e14fe3d4f338f7defa5afd67077a09a30ba40b65135b221223" + + "13238b23cd27d62cbe39173d103f8c40644701485a4ceb4f1d57b65d1a6097626a6601747874a88210871187d7939e9782a109bb40c4dbc648c911cf0cd3d9e0c6e586ebb1eda9eeaaeefcef09f49ff41ffddbfedcfec3ffa5028a03e1049807622d212fde34893b8a4a024c094c624e654ea14f7a591b67ba6b4a6cad752a778c7dbe7e7481d284d984e889598ed294d394ab98839ae5a08ca12ba2ccb1b5b8c0bbd3cca7d7a8d7dde98a07860bf1119315ac1857193f25252826284b344837f53bde43134654555755255b345f7f614d6c1471977bf8847c8b1b8c1c8c1e8ceb8cae8df38f999453a561aa6ab02dbaf3cbd4ced4d940dcaae19ce2bbe6c2ec8bf6f6fcf7ff2b05e306bc0cee1dcc2a21326d358f35473b664359447b4fcf503953ba54075bda65db65b47d9582f5842d8bec92ba93f1b22dbd4ec510ccadd0a1d39fdb16e291e46df68ffe57114f26c32b082c842d882db542ef48634be34e616ab86b3b7ba78aab8acf9160a2b7a2cea2a5a407ac69b464b8bfc710cbcbd436d673db34e4ade9deec7ef3d7faabfd1f00670126048008b208c108ca0ad5132c1fdc365941a154eb55dd565f5ff66ed678157b49826186e188f88b978d4f9e1eaeb7b06cc95fcf29d7a7d872dbd0dddff76df8d2f9400c0d0d1e0e1f0e8b12a317cb1acc1a2b1d9c273829b0354949544bec4f09679b6cf48a1c8e538e48a95fbc64c26fcecc08c31ac822e63a08445a52c45b555d035efc6ba575367afa7a6b7c4a7d7c7f538080824483218704972ba1d2a53ba75ca872ab73ab07aec1aee4b0d5b681b887b8b5bb69bd33c0a6c1aac17fc2eec3a3c61dc773c902ca87ca01d7c7d8b2d959dad1dbb2df25e326e355e77fe98ff39af69bf631fa82fc650ab00d8922f02cb132d9331f3595392148715262680974cc7acf7bab84a985c791079f68a0bea2afa89cb7e1b8bdc2c9cea0cf1ed000d181d30ee7a6e815eb9af0430910117a167d164b17fe17111a961a3d1bb51eee1f2227ec28df2cca2f7c3007328a345435e635d336544d314e245039541d55bc65c079537c3681fd8791aa92aa2eace5b27cbeb4be81c509cfdbd641d7afda97dc04df08df7ee1c7e2d8e655ee27f108fafbfe94018202cf0b3e0cda10dc10f411f511cf1c512cd9310634da34d337d437cc3bed41c767f46a426dec74247d257d5081699fe9b0c7b776bc8ac6bf059807f30a51149519f7299339e6426744c5457e464347d54c9f4e0c5a766ca87e55871d8b4ba9a9ada9af9ab59bb582b883b8b3bc06d6e5d849de40e108e709f603fa3e01450e08120e13a316eb1ffb21582c6c2fd243404c7b8c8f92a5a04ea1c1aa8bb0c4b534bde8bde9bd7dc113c755df50edf7fad8051506a108a208800a890d3011d1114b1cf91c9132db35fa3bfe3bc14376525c67b96d6e6e" + + "e87a608b9c92639612973c9cf5a68fb082b769bbd2be0ac85ac9ffd104d2aee5c5ec60f18df3dff4adf66f02d609d909430a4a20392280230627a12b342cb42d1038763e0044a2573e5e4868d4778791e59626ab1db579b6fcc26ec443c61dc8f6cfe7d8abe115eec40cd01fa728182ab1311338a840a9404d4bbd60ae627a65f86ca26e5b790990b5acb6acf4b220c69cc892016e1ace1d0b2ecd341c368b362b37bc37b53c6d3d6e3d8d41d5454d5ecf631e641c68fa7250754d7794772d782e7861907f9227ba20bb0dbf5ed85fd874e093e0d1e938ee6b13c01d162ac92c8f2e6934d23db341b5416a424b44425bba5ba0609862cb66cc6719692d703880fb87f9953a99b59da4a141ad2dae75b1c5bcbfc5f7ce2dd901eb02eb9aebd6edccf20cf5bbf596f6b3f8d2f83400ca01a10ca20c950e3c0f9b0f6528c9287329b33a52574f5a505a965e457fdd93b596d49dbfa588aa94abd4bd46e6420f7a14cb27cc27172eb72e5133db3325609f6bee6c3874007c1082ea89ec89b28a9e8e0190e6939b9a079ca49c589d1fa1aaa3fda708aae4b171b873b874b8bcb9adbd85bf90c4bad1bcd144d399d79bd716da75db76db94ddcfde70e556e71ce8ffe995ea94fa90fbe2ffec04b909ba09060cb40ff910071503162c170524b926622763273728fe29292b963a1e3d464356482e4d605222690b8c3bac16c11dcf9ee41aeaf6eca6f5aaf544057505f110f011f211a012a11295149614f7178a181319f12ae0404d51135cae672a729373fc7fe5834d88ad914f9fd1a7eec251d51ef5d204b22f3531f1318632e634e734f3387a49d34cf855ba8876a5b9beaccce60ac921093b7a4d7371d777028191819381888256835783ad848a85d4879a88ff8d008e5c8f96929792c995689902aae0acc4b972c062c4d2c97bf0cef683fc5f04530ada121c1b412d412f7c35943b204c085cfd6cf2758c784593e298e09e01a698af31b26cb83db9cdbe8cc4d9d661dd03e0dde0e1e00af60ff6e5f8bdf9bff9e1fa76fb77fb18fd97fed2138d19b236b75c7565896ff9709171159aa39de4a622a708b5f8c8e6efe718731f85210927a428a22ea838d13be75123565c73607e2d85d7a0b0b983ca4bd7b5d8c5decaea8febdcfe0b13181883212c26152eaa33133abc3abe3e115f2877e081bd903594c195c0976f9ecda005a747a71eab74b322bd33c922d3afd8b0d865da6bdbd9db97dcd8dc7dde14dfd9e079e406ee44f48df83a067706c509f40f361ee4245533dc3e55459146ff53ba548b57ff5a085c857ca17fc6943ca880b727c14ef055f622fec4063e072309860a4c1093212f25a9325633be3378349f355c366e38b539573a043b1d43384419450a4c75541e563057ad577a596060a36f86763580488331849685bd91e695009869987eafa7be" + + "50c675c839d11de42ef45ef51d001303d61475231d249a2d1732d0333938763b773b5545e746404ad54ce24fe64f8f53ab5acc655866ee6b3e6cf6733e76f377d079e1811387ae887091c7934e98f398379c80a534a770b072b002b107b93abbe5bb88bc7cc5a6c6d9cae0cdeecf90d22dd571d702dd88e602e729e872eb7deda5f22b05960b591d5b1db41f8d3f6252525c545c9b600678758276896a961d9967a278b319c75dceaad23ed75ddc3ce864f417fa11fca8fd5efe06ff90ff91ffe300e40097019801ba03c1058907e608e908c40e5b14ff14f61b9a1d5e2b93368a43c5475e484b4bc24cbd4d364ec5517e540a56b756bc56c156d85a6c5df060b06224664269af6cd06dd16dd36d6d6e307149722173d8782a7b5c88af93a095f09e4ea1b4a1c4a486bd03c68cc981ccd6cd4dd1add44ed540dfe3ef3af2f2fc6f03e704a306eb11f4162518b41b9f1e922537326538f44916527f5b12629c62d667926a926e40735e74697a537d2a7e3184eb99d39da69f1aa5dcaa91ac9eb16eba4ebdc4bd85beefbfbdc0b0cb35ceaad6fbd75fda62dffce6b0eb7fee3103c9034e071411ee303535bd368b3f5c436443924ea253195847610c641d667e6b236c256ca36df273a974eb75a878f479ac7d498ef78fdd909894aa955999f79aeaa256a440a7e4a714aa57ad21b7acbdb2c995cc97cc28cdb2ce82cf9cd422d6d5f53ffbaefc00050c07c1162b1fde2234320a45c646d84de34d64511a62c06f88731d77d177da8ce490faa467bcdac187c2b6c8b8c8ebca14cd44d084d1cfd320d89adee0f13e0167081216362ba9303e315334d444d945db452c48804d5b4e044fcf504c6128639f66506f23847f853f86408cdcb274bca3c2c9c25bcd16d98ef6f406b208ce0ccf0c8117f71ace2b0c30bc3a433de63e174418444e459546694a594bde518153995aaa5d4a5e105f885fc15f896724685b6c756f2f74b075667e638230855b871eaa9eaa10af7baf26b896c3abca6cd8a7db19f4a6fe78ff5613ae13cc186b33203d5a3fc140f94f8459ec6f9575379c40b5f0b521b72fc043c625c752cc74d32cd6e5d6f9e098e401e773ea67f468f404f54af910fa3dfb3efb4bfe0dffc5181c1d911d17313b78e892bd948ca25ca382a684a65ec337c4d7c4e0ce64daccdbc3de0fe04dea80ec3eed40ede300280dca27b028812e573e8752147b3685fc983d9d0ea991bfddc591c692c602d175d3bad551d61ed929e06ee29bf47ff780fde5092e35143cc4514b570a64b46cd7762e796d88899261b78bba58bc34d635d6ffe0b3019518d521ec2335273627612b9a3299375e3818421a42c242a0447f4bc9588b5cb86a8e6f0b87a49959a3aba52aaa68add6c448ce2fcfb8d2b2dfc9e6e302f712f812ff15342175493d6df474927a8491bf927d9d" + + "1ca420cc4cd67ada41f493f7951a2d2140297f32dd342f351f376f387138f3397c3aa33da43dc645d54c44527f53a0566457b65d20649f75e97d71860f89878b2f8c618ca78cb48fa397d9a78aa861aaacacb8ae5db0beb22ab62cb6bbb7e3c344ccd0d197d230d836de17e366e4a5eaa1ed81f86009c20cfa12dc15dd15f41ad11bb41c242eaf374d4f29520453b1536d5ecc63af6d0f73207b3c80a9811489948d558f09943195f395f1991c9bc69e7ea6ccac83af95bc63bdc0cfc1d590da4ddf4fdf6ced6af22eff300fee118418f53a103f4c488852f255266a276d417d9185f9869295cca41caa6cabe3b9fbbb6ec17fcdefd54ce214e4cdf466f822f9e8f913002b04d20405084915ef16281b9d1d9f1d641f651f2622ca254b28b9296d2ac82dc92d612f6051175adb68446c217077722c7c73877d99b99dcc9fd49f86a2abd6e5eb9decf9eda5f0900e4a1e531e591e0b22892d6e44ae48ba60eb636897e5c32bd3e8d718d8b8d8a0e540eac5f650f88b04290f2a14f621b8222c2c4a303035c5450c490e4c1652b65e9e614c68246925692c69f569b5702c724d764e76027c047cbd7ef18369855c89b98cf4a3d9a885be38c1d1e1d2e16de502e6f8f062f60714f715da1eae2dd537553aab3f0c5939646d81c99b97a16caa02ccc1ccefd04fd91cdcb8dc3ee222e75ae82bea61ee3af53bf56b163d3d3c40a94170815288b98c54915791ac96369a3abf51c288c9a1e75c1c9a273c2a3d2acb2c0a2f2232825e3e64198db9968ea13cd0e2d0fed2bdd6bfd966daade776efdbf367f61af731218c2a0b2b152b392dd22dd32d20319d3140324132f63343354435743675368b42b14b3050f15574560b574f5a3c5eb369e769f1787184678d378e44911e949f9987a1eda311a835b882bc99bf2ec681c995d517e7a6e899f4940bef1182142115be1c1a215f447255ee58855bfc5c34600763e869eb75bd776b780c7f42850188f08b53918cb778bcb7caefd3bedb5ddeabe4e10c4919172d765555562f57495c075d615eed60986b9c7c9e7c4c8ef9d3cae91d16a11f2e2326297b39033a9a3b64458747134f0051ba5c045f7a614168446beb72c27355766c773e7a9a7d6c85fa88ca9443983d9cdaa344a621aa15ac2ab0f8b273b8ebb9c4bc42bfb1c154c307c9a5c995cc6fce19cf41d05fd41ed561dbfbdb76dcdedd5ee71ee806efe7f2f004660ca81f5036b66319776e8a478f0099a19ed9aa44af2eb6f0b768cd65cfbfe23de526eb83244f2699367c3dc0462a49a2679d6a146b756f737e747edd9616a2f6ca5f0ac33b3a5fe062936652801fc4e6c4e1c5a0c7d2cad4ca92cd0bd20edca8dc6be3d0ede1f02ff233f2def29df72dfd2efddfff390598125e1c6e26e635ae36493c7d3d6b4107425f43994df469746f5b782e7daa8f" + + "e8901e96779934a257ad73b7afc5d4e6d20cb310801b7d3fc35a30726b7f1e85818b908d069c8a9cadaa06b5abc32ae2790afa3a303e5e4c9b643079627a9a7afe7c2d83488ae698e79874ad14b046bc28c045d342f539f9940aa40d2324f92b65348f3df63f084d894d4d514f51bc527c63a673e59fa7abbbae1fb8e6c0bfd9dbe2a9073e0b990f96149f29fa365939453afd433c6074687b6c177f28803981238b828c178ec092b894ad95ae95b095199753bbe1bf0ccb63e1d0e7cfea8ff06cfb26049805cd052f0b75135325272ca4429c51075eca5f37614d6dc972f78a828bc594cc9e1daa51c037c27dd464ddb901c603af070228d03018443b458c5045677a6a0c77c286c48dff91b998e19aea9e72a17da988adafb9ebc1c4c959cef0e094e7d6ead7f596fc82ffad085e09e90cc61cf91d181e5f274635e338173c44464746174a64503151b752ac58f659f65a735b745b235cb95cee5da15f30606473f774d87a1b7ea48827a004af62bccfd53fddfae01ce690e7e9ed26f2b2f25ff8b2044a07670c442c8235fb46bf48e949ba4c4069346d347365739e73ed8ae68fe69ab2a61da85babe2b197b282bb36c021c2a7c5a8c544c663c734cae1d1dbd62fda82dbe6debce0a9e3e9e643e844e845e825ebecebedebf0ec76ed11efa2efa3eff4f2fdf313f7f7fb74091a0a150fd412221a0c23192aaa407f56e95e3564ea703e77798b4f8c4b9f7aa2b5a551b585b5dcb6edbabcbb4fbc4ad6b6dc2cee1fef30f692f7fcffe5022c08940ec210312274290e2b4432cc3cf859f959fe598261377298764877bd7f548c468e488f80912893c59af39e37a3ada7d1afd1b316b5e4b7cfb9d0b9d1b94bbd36c932d6b3dbf0e1d4e3d5e367e8f4e924ef22f7f6f850f971fa10060a0a950f911380191e1ac91a441cb01fbe239a309a4a1870d870e6700d726574daa481b59ac780c8dcc869e66de672e676e620ef4ef605fe1701b10b8e17ad1d5a26b7267532c538913ae641ed5344542355c356c756e960f5677a6c4f8064836e93419ad2a0c2a7a4bd33c1e5c134c4f3c642c9e0cbd0d126d341d932e2daf045f2e1faa5ff63020704fc16061e021f4820bf28ed3bad3d9a4a06546458225ce55c00694070bb74457b3a833c8b8a8df999bbd06ed9eae170ea24ed48f52df8dbfd32050a09770d28214d35c938c33a2d3ede43c85c406e627d7687849cdea76bb029b254b306c7b9c798cd1ddaadfb9efca6fe6e00d7078f09cb22a5393b3a0e3fb549474d275b065dde5dc65eae6136838186e29dc6a0f5a214af6fb86ebc6fbc6abe00cc51ea0af46613ed13c831e547c6481058cb59ca5d44a130a751b486d1ebdfd9e0f9e2b3e342eba5f0bef615f957122b20fb24fc241827492a182b112cda2c75305931063a9564ab904d96f0aac6abc7ab" + + "3bc4acd1a9d9e4df98e012e416e4890db01dbf21cc38bf73c1838193bb949195a897439caea60ba921ae53b059bd6bc792c87ac97bc981cf82e448f77ff9abfae4fd9e0ef318851aad1dad380a3b824d574e584e37505b577457375eeb60af77fc787c7c4e7dd87e29802c8037821e92ad946c97a2a9bcb1beb15cc021ce38d738e1cbe20aed31edcf035113e814f7150e1c11250626df29aa2cad305f3161310632d733e837ae43a44b2c4e224fd04fa151a251bf59c45b5d5cb65cd95de1641a67506ce7712a826d84ce90ce99609e639e859fdda294a7ceacd2ac07af33b102bd0abff2c730ca42cc4bd050d057d536d937d938d938de26e0f2e1dceddfed69f29dfb5401c7018412de146e1870183f1ef220f73665381c3fad409f44d9461f4ac951ff546a563b58885cb6602563736574653f6647661170c8700d752b81f38181828d846985ea89fe91879b889b689c9e9e9f9efda05ca2a2ac07ae8ab142b222c50dc69bd1b1d65ad930da54deaedf6fe08de2cde5fbe9bdea73eebbee0df9c7fa3300c8059e0d7715ec24d3294f336e357e3cbc3cfa40374559467a47e148d3506852745768596d5c9f678f6e03708e7343746775cd78be7cf87d1085e888a98bf590dd9b009ebea698c2ced844debeeec2f09af123f62c0ea11753278b2b964044488453f355f5553a60ed71ef71958c7591ae9b1da79ba7d0b0c5b378bc7ac683d05ed1d6d5d7d599d952daf7dacddccfdcabe1dfe3e0e33ae90aeea9f0abf06cf1b7f2a202a4035410a418a025aa3864457668e06acb82208e74934698bba595bc1ebf6ebf68cb75d4c8d823df35040614f91513262a2d6f386e39a239d63a053e8c3e183f87402b46c3490d4d774f3555fc57ec594064b565b9656e684a6dff71397660837c84eb85f985538951910d9319945ba1cba38fab24b844ba00be19c16bcb6ccb13d008d521d9f2dda3e06be16ce1b8e3d9e7a0ec62f28af646067d08d90e4d1083134c149b1f3522362283248424cd26ce269127442f4b2f59305a30a733a933e636e63768392c3c7d3da03fa13fd745a94817491849f254a065f767ec6bce6dd86fe77d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080dfdfbb4e0460fedffffffffffffffffffffeffffffffffffdfffffffffffffffbfffff7ffffffffffbff7ffffffffdffffdffffffffefffffdbffffff7ffffbffffffffeffffbfffeffffbfdffffffff7fff7f7fff7f7fdfef7fffbffffddfef7fffefbfffdfffef" + + "ffdbfffffe7fffefef7fffdff7f7fbefeff7f7f77ffff7fffd7fff7ebfdaf77fbfbdffba6dfbdbdef66adbd17777abffb77f7a25eff65d7bed52aa77f355d6596dfdffffa4cbaed5ea7699edffffffffffffffbf7a1edf7b7ff56ead7dbf6f7ddefd7ee6eeae7afbbedefaffffcbfcfbffffffffffefedcdeef7f5fbdf7deffddede7dbbf77fffdbf5edbbdd5fd7ee9bf77bbf7577dffdfeedffff77ffffffffffcfdedffefefedeffeebbfb7dddf9dd9fb77ceff4d52bbeefdbeffa7efdbedd7eef9ebbef776fdefbb7dbbfffbdf7f7f7fdedfbefffffbf6ffbffff77ed7d6f9eb7fadefbf7eeedbedbed2db5bf6fb7ceeffe7dbfffd7dff7effdffffeffffffbd4efb3bbf7fbefd7b7fdefffffffdbfffffffefbbeffffff7eefefdeefbfdffd767ffffdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffff6ef7ef7f7fbfdebfbfb7bfbfffffbff7f7ffffdf7d7ff77bdfbbdbdfbbffef7edf75ffffffefefdfbffdbefffbbd775ffffddfdf7fffdedf7ff7bfff7fff7fffffbfffeffffef7fffffffffdffbffff7f7fbfffefbfffffffffdf7dffff7fffedffffd7fffeffffffdfffffbfdf7ffefffdfffbffffffbffbffffdff7effffbffffffffffdbfefff7fdfffffffffeffffffefffbbfddffbffffdfdfff7fbdffffffefffffefdeffffbdfff7dffdfffeffbfff7ffeffbeffffffe7dfffbfffffffffbfffffffffffffeffffffbffff7fbfffffffbdffffd7ffffffefffefdff7effdfffffefff7ffff7fdfff7fffffffffbffffeffffffbfffffffffefbffbfffdfbfffefff7ffffffdffbfffffffffdffffffbfffffeffbffffffffffdffdffffeff7ffffffbffffffffff7ffffffffffffffffdfffffb7fffffeffffff77fffeffffffeffdffffffffdffffffdfffeffffdffdffffffffdff7ffffeffffffbffffffffffbffffdfff7ffffffffefffefffdffeffffffbfffffffffdfffffffefffff7fffb7ffffff7ff7ffffffeffefffffdffff7ffffffffffbfffffffbffffffffffffffffffffffffffffffffffffffdfffeffdffffffffbffffefffeffffffffdffffbfffbffffff7ffbffffff7fffffdfff7ffffffffdffffffffffeffffbffffffffffffffffbf7ffffffffffbfffffbfffffff7ffffffffffffeffffffdffffffffffffffdffffffffff7fffbfffffffffffffffdfffffffbffffffffbffffffeffffffffffffdffff7fffffff7ffffffffffffffeffffffffffeffffffffffffffffffffff7fffffffffffffffbffffffffefffffffffdfffffffffffffffffffffbffffffffffffffffefffffffffffffeffffffffffffff7ffffffffffffffffeffffffffffffffffbfffffffffffffdfffffffffffffffffdffffffffffffffffbfffffffffdffffffbfffffff" + + "7ffffffffffffffbffffffffffffbfffffff7fffffffffffffffffffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdffffffffdfffffffeffffbffffffffffffbfffffffefffffeffdfffbfffffffeffffffffbfffffbffbffffffffffffff7ffffffdffffffffffefffffdffffffbffffffffffffffdfffffffffffdfffffbffffffffffbfffffffffbffffffffffffbffffffffffefffffffffff7ffffffffffff7ffffffdffffffffeffffeffffffffff7ffffffffffeffffffffffffbffffbffffffffff7ffffffbffffffffffbfffffffffffff7fffffeffff7ffffffffffffbfffffffffffefffffffffffffffffeffffffffffefffffffffbfffffffffffdffffffffffdffffffeffffffffffefffffdffffffffffffbffffffffffeffffffffffdffffffff7ffffffbffffffffdfffffffffbfffffffbfffffeffffffefffffffff7ffffffffeffffffffff7ffffffffffeffffdfffdfffffffbfffffffffdfffdfffffefffffffffefffffdffffffffffff7ffffffffffff7fffffff7ffffffffffffffffffefffffffffffeffffffffffdfffffffbfffffffdfffffffffffdffffffffffdfffffdffffefffbfffffffbffffffdffffffffffbffffffffffffbffff7fffffffffdffffffbfffffffff7ffffbfffbfffffbfffffffffffeffffffffbfff7fffffffffffff7ff7fff7ffffffffbffffefffdffffffbfffffefffffffdfffffdfffffffeffffffffeffffffffffffffbfffffffbfffffffffffbfffffffefffffffffeffff7ffffffffdffffdffffffbffffefffff7ffffffffff7fffffffffffffffbfffffffffffffff7ffffffff7fffffffff7fffffdfffffffffffffbfffffffff1f00000000000000ff43000000000000000000001a01000025020000390300005a040000c205000000070000380800007f090000ba0a0000e20b0000f40c0000040e00002c0f00004210000053110000641200007b1300008714000096150000a3160000ae170000b9180000c4190000ce1a0000d51b0000df1c0000e61d0000ed1e0000f21f0000f7200000fb210000ff22000005240000062500000f260000182700001e280000242900002b2a0000312b0000382c00003e2d0000462e00004f2f0000543000005d310000643200006e330000763400007f350000843600000000000000000000" + buf := hexutility.MustDecodeHex(raw) + ef := NewEliasFano(1, 1) + ef.Reset(buf) + + first := ef.Get(0) + second := ef.Get(1) + + // This test does a seek in a reverse iterator for the 0th value of the sequence. + // + // Data is specially crafted so the 0th element is represented by setting the 63th bit in the upper bytes word and + // the 1st element is the 0th bit of the next word. + // + // So the implementation positions the iterator at the (current value == 1st value) and the next value should take + // the last bit of the previous upper word. + t.Run("reverse seek 63th upper bit", func(t *testing.T) { + it := ef.ReverseIterator() + it.Seek(first) + }) + + t.Run("seek 0th upper bit", func(t *testing.T) { + it := ef.Iterator() + it.Seek(second) + }) +} + func TestEliasFanoSeek(t *testing.T) { count := uint64(1_000_000) maxOffset := (count - 1) * 123