From 981b18d8250568d5d653fda4cfc9543b6c7e96c7 Mon Sep 17 00:00:00 2001 From: Urvi Date: Thu, 6 Jun 2024 14:22:37 -0700 Subject: [PATCH] Delete lighthorizon --- Makefile | 3 +- exp/lighthorizon/actions/accounts.go | 142 ------ exp/lighthorizon/actions/accounts_test.go | 191 ------- exp/lighthorizon/actions/apidocs.go | 26 - exp/lighthorizon/actions/main.go | 124 ----- exp/lighthorizon/actions/problem.go | 94 ---- exp/lighthorizon/actions/root.go | 29 -- exp/lighthorizon/actions/static/api_docs.yml | 228 --------- exp/lighthorizon/adapters/account_merge.go | 21 - exp/lighthorizon/adapters/allow_trust.go | 43 -- .../begin_sponsoring_future_reserves.go | 15 - exp/lighthorizon/adapters/bump_sequence.go | 17 - exp/lighthorizon/adapters/change_trust.go | 63 --- .../adapters/claim_claimable_balance.go | 26 - exp/lighthorizon/adapters/clawback.go | 37 -- .../adapters/clawback_claimable_balance.go | 22 - exp/lighthorizon/adapters/create_account.go | 18 - .../adapters/create_claimable_balance.go | 27 - .../adapters/create_passive_sell_offer.go | 51 -- .../end_sponsoring_future_reserves.go | 38 -- exp/lighthorizon/adapters/inflation.go | 12 - .../adapters/liquidity_pool_deposit.go | 33 -- .../adapters/liquidity_pool_withdraw.go | 24 - exp/lighthorizon/adapters/manage_buy_offer.go | 52 -- exp/lighthorizon/adapters/manage_data.go | 23 - .../adapters/manage_sell_offer.go | 52 -- exp/lighthorizon/adapters/operation.go | 93 ---- .../adapters/path_payment_strict_receive.go | 78 --- .../adapters/path_payment_strict_send.go | 78 --- exp/lighthorizon/adapters/payment.go | 35 -- .../adapters/revoke_sponsorship.go | 66 --- exp/lighthorizon/adapters/set_options.go | 122 ----- .../adapters/set_trust_line_flags.go | 83 --- .../adapters/testdata/transactions.json | 67 --- exp/lighthorizon/adapters/transaction.go | 295 ----------- exp/lighthorizon/adapters/transaction_test.go | 81 --- exp/lighthorizon/build/README.md | 24 - exp/lighthorizon/build/build.sh | 56 -- exp/lighthorizon/build/index-batch/Dockerfile | 20 - exp/lighthorizon/build/index-batch/README.md | 7 - exp/lighthorizon/build/index-batch/start | 17 - .../build/index-single/Dockerfile | 25 - exp/lighthorizon/build/k8s/ledgerexporter.yml | 125 ----- .../build/k8s/lighthorizon_batch_map_job.yml | 43 -- .../k8s/lighthorizon_batch_reduce_job.yml | 42 -- .../build/k8s/lighthorizon_index.yml | 74 --- .../build/k8s/lighthorizon_web.yml | 133 ----- .../build/ledgerexporter/Dockerfile | 33 -- .../build/ledgerexporter/README.md | 42 -- .../ledgerexporter/captive-core-pubnet.cfg | 200 -------- .../ledgerexporter/captive-core-testnet.cfg | 32 -- exp/lighthorizon/build/ledgerexporter/start | 55 -- exp/lighthorizon/build/web/Dockerfile | 24 - exp/lighthorizon/common/operation.go | 52 -- exp/lighthorizon/common/transaction.go | 70 --- exp/lighthorizon/http.go | 78 --- exp/lighthorizon/http_test.go | 64 --- exp/lighthorizon/index/Makefile | 24 - exp/lighthorizon/index/backend/backend.go | 14 - exp/lighthorizon/index/backend/file.go | 214 -------- exp/lighthorizon/index/backend/file_test.go | 43 -- exp/lighthorizon/index/backend/gzip.go | 74 --- exp/lighthorizon/index/backend/gzip_test.go | 61 --- .../index/backend/parallel_flush.go | 73 --- exp/lighthorizon/index/backend/s3.go | 220 -------- exp/lighthorizon/index/builder.go | 366 -------------- exp/lighthorizon/index/cmd/batch/doc.go | 52 -- exp/lighthorizon/index/cmd/batch/map/main.go | 144 ------ .../index/cmd/batch/reduce/main.go | 389 -------------- exp/lighthorizon/index/cmd/map.sh | 96 ---- exp/lighthorizon/index/cmd/mapreduce_test.go | 232 --------- exp/lighthorizon/index/cmd/reduce.sh | 75 --- exp/lighthorizon/index/cmd/single/main.go | 59 --- exp/lighthorizon/index/cmd/single_test.go | 279 ---------- exp/lighthorizon/index/cmd/testdata/latest | 1 - .../index/cmd/testdata/ledgers/1410048 | Bin 4160 -> 0 bytes .../index/cmd/testdata/ledgers/1410049 | Bin 5340 -> 0 bytes .../index/cmd/testdata/ledgers/1410050 | Bin 5136 -> 0 bytes .../index/cmd/testdata/ledgers/1410051 | Bin 4872 -> 0 bytes .../index/cmd/testdata/ledgers/1410052 | Bin 5052 -> 0 bytes .../index/cmd/testdata/ledgers/1410053 | Bin 3896 -> 0 bytes .../index/cmd/testdata/ledgers/1410054 | Bin 2820 -> 0 bytes .../index/cmd/testdata/ledgers/1410055 | Bin 2968 -> 0 bytes .../index/cmd/testdata/ledgers/1410056 | Bin 6084 -> 0 bytes .../index/cmd/testdata/ledgers/1410057 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410058 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410059 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410060 | Bin 4084 -> 0 bytes .../index/cmd/testdata/ledgers/1410061 | Bin 5944 -> 0 bytes .../index/cmd/testdata/ledgers/1410062 | Bin 6732 -> 0 bytes .../index/cmd/testdata/ledgers/1410063 | Bin 6004 -> 0 bytes .../index/cmd/testdata/ledgers/1410064 | Bin 5940 -> 0 bytes .../index/cmd/testdata/ledgers/1410065 | Bin 4992 -> 0 bytes .../index/cmd/testdata/ledgers/1410066 | Bin 4004 -> 0 bytes .../index/cmd/testdata/ledgers/1410067 | Bin 6092 -> 0 bytes .../index/cmd/testdata/ledgers/1410068 | Bin 4864 -> 0 bytes .../index/cmd/testdata/ledgers/1410069 | Bin 4084 -> 0 bytes .../index/cmd/testdata/ledgers/1410070 | Bin 3928 -> 0 bytes .../index/cmd/testdata/ledgers/1410071 | Bin 2900 -> 0 bytes .../index/cmd/testdata/ledgers/1410072 | Bin 5316 -> 0 bytes .../index/cmd/testdata/ledgers/1410073 | Bin 5080 -> 0 bytes .../index/cmd/testdata/ledgers/1410074 | Bin 5928 -> 0 bytes .../index/cmd/testdata/ledgers/1410075 | Bin 6060 -> 0 bytes .../index/cmd/testdata/ledgers/1410076 | Bin 3876 -> 0 bytes .../index/cmd/testdata/ledgers/1410077 | Bin 3700 -> 0 bytes .../index/cmd/testdata/ledgers/1410078 | Bin 5132 -> 0 bytes .../index/cmd/testdata/ledgers/1410079 | Bin 4852 -> 0 bytes .../index/cmd/testdata/ledgers/1410080 | Bin 4704 -> 0 bytes .../index/cmd/testdata/ledgers/1410081 | Bin 6180 -> 0 bytes .../index/cmd/testdata/ledgers/1410082 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410083 | Bin 5916 -> 0 bytes .../index/cmd/testdata/ledgers/1410084 | Bin 6220 -> 0 bytes .../index/cmd/testdata/ledgers/1410085 | Bin 5972 -> 0 bytes .../index/cmd/testdata/ledgers/1410086 | Bin 4528 -> 0 bytes .../index/cmd/testdata/ledgers/1410087 | Bin 3704 -> 0 bytes .../index/cmd/testdata/ledgers/1410088 | Bin 4048 -> 0 bytes .../index/cmd/testdata/ledgers/1410089 | Bin 5080 -> 0 bytes .../index/cmd/testdata/ledgers/1410090 | Bin 3696 -> 0 bytes .../index/cmd/testdata/ledgers/1410091 | Bin 2680 -> 0 bytes .../index/cmd/testdata/ledgers/1410092 | Bin 2904 -> 0 bytes .../index/cmd/testdata/ledgers/1410093 | Bin 4696 -> 0 bytes .../index/cmd/testdata/ledgers/1410094 | Bin 4628 -> 0 bytes .../index/cmd/testdata/ledgers/1410095 | Bin 5132 -> 0 bytes .../index/cmd/testdata/ledgers/1410096 | Bin 7196 -> 0 bytes .../index/cmd/testdata/ledgers/1410097 | Bin 6016 -> 0 bytes .../index/cmd/testdata/ledgers/1410098 | Bin 7080 -> 0 bytes .../index/cmd/testdata/ledgers/1410099 | Bin 4708 -> 0 bytes .../index/cmd/testdata/ledgers/1410100 | Bin 4844 -> 0 bytes .../index/cmd/testdata/ledgers/1410101 | Bin 3860 -> 0 bytes .../index/cmd/testdata/ledgers/1410102 | Bin 5768 -> 0 bytes .../index/cmd/testdata/ledgers/1410103 | Bin 5580 -> 0 bytes .../index/cmd/testdata/ledgers/1410104 | Bin 4964 -> 0 bytes .../index/cmd/testdata/ledgers/1410105 | Bin 4984 -> 0 bytes .../index/cmd/testdata/ledgers/1410106 | Bin 5080 -> 0 bytes .../index/cmd/testdata/ledgers/1410107 | Bin 4032 -> 0 bytes .../index/cmd/testdata/ledgers/1410108 | Bin 2968 -> 0 bytes .../index/cmd/testdata/ledgers/1410109 | Bin 5084 -> 0 bytes .../index/cmd/testdata/ledgers/1410110 | Bin 2740 -> 0 bytes .../index/cmd/testdata/ledgers/1410111 | Bin 5212 -> 0 bytes .../index/cmd/testdata/ledgers/1410112 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410113 | Bin 4708 -> 0 bytes .../index/cmd/testdata/ledgers/1410114 | Bin 4644 -> 0 bytes .../index/cmd/testdata/ledgers/1410115 | Bin 4868 -> 0 bytes .../index/cmd/testdata/ledgers/1410116 | Bin 4696 -> 0 bytes .../index/cmd/testdata/ledgers/1410117 | Bin 5836 -> 0 bytes .../index/cmd/testdata/ledgers/1410118 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410119 | Bin 7452 -> 0 bytes .../index/cmd/testdata/ledgers/1410120 | Bin 6060 -> 0 bytes .../index/cmd/testdata/ledgers/1410121 | Bin 5948 -> 0 bytes .../index/cmd/testdata/ledgers/1410122 | Bin 4908 -> 0 bytes .../index/cmd/testdata/ledgers/1410123 | Bin 3924 -> 0 bytes .../index/cmd/testdata/ledgers/1410124 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410125 | Bin 2496 -> 0 bytes .../index/cmd/testdata/ledgers/1410126 | Bin 2752 -> 0 bytes .../index/cmd/testdata/ledgers/1410127 | Bin 3928 -> 0 bytes .../index/cmd/testdata/ledgers/1410128 | Bin 4960 -> 0 bytes .../index/cmd/testdata/ledgers/1410129 | Bin 3976 -> 0 bytes .../index/cmd/testdata/ledgers/1410130 | Bin 5184 -> 0 bytes .../index/cmd/testdata/ledgers/1410131 | Bin 5880 -> 0 bytes .../index/cmd/testdata/ledgers/1410132 | Bin 6120 -> 0 bytes .../index/cmd/testdata/ledgers/1410133 | Bin 5292 -> 0 bytes .../index/cmd/testdata/ledgers/1410134 | Bin 5124 -> 0 bytes .../index/cmd/testdata/ledgers/1410135 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410136 | Bin 5036 -> 0 bytes .../index/cmd/testdata/ledgers/1410137 | Bin 5144 -> 0 bytes .../index/cmd/testdata/ledgers/1410138 | Bin 3876 -> 0 bytes .../index/cmd/testdata/ledgers/1410139 | Bin 4908 -> 0 bytes .../index/cmd/testdata/ledgers/1410140 | Bin 3924 -> 0 bytes .../index/cmd/testdata/ledgers/1410141 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410142 | Bin 6092 -> 0 bytes .../index/cmd/testdata/ledgers/1410143 | Bin 5960 -> 0 bytes .../index/cmd/testdata/ledgers/1410144 | Bin 6080 -> 0 bytes .../index/cmd/testdata/ledgers/1410145 | Bin 3976 -> 0 bytes .../index/cmd/testdata/ledgers/1410146 | Bin 3896 -> 0 bytes .../index/cmd/testdata/ledgers/1410147 | Bin 2840 -> 0 bytes .../index/cmd/testdata/ledgers/1410148 | Bin 2920 -> 0 bytes .../index/cmd/testdata/ledgers/1410149 | Bin 2744 -> 0 bytes .../index/cmd/testdata/ledgers/1410150 | Bin 6084 -> 0 bytes .../index/cmd/testdata/ledgers/1410151 | Bin 4796 -> 0 bytes .../index/cmd/testdata/ledgers/1410152 | Bin 4748 -> 0 bytes .../index/cmd/testdata/ledgers/1410153 | Bin 6116 -> 0 bytes .../index/cmd/testdata/ledgers/1410154 | Bin 5896 -> 0 bytes .../index/cmd/testdata/ledgers/1410155 | Bin 5132 -> 0 bytes .../index/cmd/testdata/ledgers/1410156 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410157 | Bin 3796 -> 0 bytes .../index/cmd/testdata/ledgers/1410158 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410159 | Bin 4708 -> 0 bytes .../index/cmd/testdata/ledgers/1410160 | Bin 4644 -> 0 bytes .../index/cmd/testdata/ledgers/1410161 | Bin 7296 -> 0 bytes .../index/cmd/testdata/ledgers/1410162 | Bin 7176 -> 0 bytes .../index/cmd/testdata/ledgers/1410163 | Bin 4700 -> 0 bytes .../index/cmd/testdata/ledgers/1410164 | Bin 2920 -> 0 bytes .../index/cmd/testdata/ledgers/1410165 | Bin 4032 -> 0 bytes .../index/cmd/testdata/ledgers/1410166 | Bin 7036 -> 0 bytes .../index/cmd/testdata/ledgers/1410167 | Bin 3856 -> 0 bytes .../index/cmd/testdata/ledgers/1410168 | Bin 5648 -> 0 bytes .../index/cmd/testdata/ledgers/1410169 | Bin 5600 -> 0 bytes .../index/cmd/testdata/ledgers/1410170 | Bin 3876 -> 0 bytes .../index/cmd/testdata/ledgers/1410171 | Bin 4908 -> 0 bytes .../index/cmd/testdata/ledgers/1410172 | Bin 3924 -> 0 bytes .../index/cmd/testdata/ledgers/1410173 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410174 | Bin 4704 -> 0 bytes .../index/cmd/testdata/ledgers/1410175 | Bin 4860 -> 0 bytes .../index/cmd/testdata/ledgers/1410176 | Bin 6248 -> 0 bytes .../index/cmd/testdata/ledgers/1410177 | Bin 7168 -> 0 bytes .../index/cmd/testdata/ledgers/1410178 | Bin 5828 -> 0 bytes .../index/cmd/testdata/ledgers/1410179 | Bin 4932 -> 0 bytes .../index/cmd/testdata/ledgers/1410180 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410181 | Bin 2840 -> 0 bytes .../index/cmd/testdata/ledgers/1410182 | Bin 3872 -> 0 bytes .../index/cmd/testdata/ledgers/1410183 | Bin 4904 -> 0 bytes .../index/cmd/testdata/ledgers/1410184 | Bin 3920 -> 0 bytes .../index/cmd/testdata/ledgers/1410185 | Bin 3840 -> 0 bytes .../index/cmd/testdata/ledgers/1410186 | Bin 2840 -> 0 bytes .../index/cmd/testdata/ledgers/1410187 | Bin 5164 -> 0 bytes .../index/cmd/testdata/ledgers/1410188 | Bin 4908 -> 0 bytes .../index/cmd/testdata/ledgers/1410189 | Bin 7128 -> 0 bytes .../index/cmd/testdata/ledgers/1410190 | Bin 5108 -> 0 bytes .../index/cmd/testdata/ledgers/1410191 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410192 | Bin 4708 -> 0 bytes .../index/cmd/testdata/ledgers/1410193 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410194 | Bin 6092 -> 0 bytes .../index/cmd/testdata/ledgers/1410195 | Bin 4864 -> 0 bytes .../index/cmd/testdata/ledgers/1410196 | Bin 4992 -> 0 bytes .../index/cmd/testdata/ledgers/1410197 | Bin 4004 -> 0 bytes .../index/cmd/testdata/ledgers/1410198 | Bin 4828 -> 0 bytes .../index/cmd/testdata/ledgers/1410199 | Bin 4828 -> 0 bytes .../index/cmd/testdata/ledgers/1410200 | Bin 6368 -> 0 bytes .../index/cmd/testdata/ledgers/1410201 | Bin 4928 -> 0 bytes .../index/cmd/testdata/ledgers/1410202 | Bin 4612 -> 0 bytes .../index/cmd/testdata/ledgers/1410203 | Bin 4168 -> 0 bytes .../index/cmd/testdata/ledgers/1410204 | Bin 3992 -> 0 bytes .../index/cmd/testdata/ledgers/1410205 | Bin 6092 -> 0 bytes .../index/cmd/testdata/ledgers/1410206 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410207 | Bin 4864 -> 0 bytes .../index/cmd/testdata/ledgers/1410208 | Bin 4992 -> 0 bytes .../index/cmd/testdata/ledgers/1410209 | Bin 5012 -> 0 bytes .../index/cmd/testdata/ledgers/1410210 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410211 | Bin 11720 -> 0 bytes .../index/cmd/testdata/ledgers/1410212 | Bin 6068 -> 0 bytes .../index/cmd/testdata/ledgers/1410213 | Bin 6184 -> 0 bytes .../index/cmd/testdata/ledgers/1410214 | Bin 5112 -> 0 bytes .../index/cmd/testdata/ledgers/1410215 | Bin 6116 -> 0 bytes .../index/cmd/testdata/ledgers/1410216 | Bin 6016 -> 0 bytes .../index/cmd/testdata/ledgers/1410217 | Bin 3984 -> 0 bytes .../index/cmd/testdata/ledgers/1410218 | Bin 4336 -> 0 bytes .../index/cmd/testdata/ledgers/1410219 | Bin 2920 -> 0 bytes .../index/cmd/testdata/ledgers/1410220 | Bin 2900 -> 0 bytes .../index/cmd/testdata/ledgers/1410221 | Bin 3028 -> 0 bytes .../index/cmd/testdata/ledgers/1410222 | Bin 5372 -> 0 bytes .../index/cmd/testdata/ledgers/1410223 | Bin 5500 -> 0 bytes .../index/cmd/testdata/ledgers/1410224 | Bin 6136 -> 0 bytes .../index/cmd/testdata/ledgers/1410225 | Bin 6004 -> 0 bytes .../index/cmd/testdata/ledgers/1410226 | Bin 5920 -> 0 bytes .../index/cmd/testdata/ledgers/1410227 | Bin 6140 -> 0 bytes .../index/cmd/testdata/ledgers/1410228 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410229 | Bin 4728 -> 0 bytes .../index/cmd/testdata/ledgers/1410230 | Bin 4808 -> 0 bytes .../index/cmd/testdata/ledgers/1410231 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410232 | Bin 4796 -> 0 bytes .../index/cmd/testdata/ledgers/1410233 | Bin 5052 -> 0 bytes .../index/cmd/testdata/ledgers/1410234 | Bin 5436 -> 0 bytes .../index/cmd/testdata/ledgers/1410235 | Bin 5156 -> 0 bytes .../index/cmd/testdata/ledgers/1410236 | Bin 5044 -> 0 bytes .../index/cmd/testdata/ledgers/1410237 | Bin 3036 -> 0 bytes .../index/cmd/testdata/ledgers/1410238 | Bin 5196 -> 0 bytes .../index/cmd/testdata/ledgers/1410239 | Bin 5412 -> 0 bytes .../index/cmd/testdata/ledgers/1410240 | Bin 3280 -> 0 bytes .../index/cmd/testdata/ledgers/1410241 | Bin 5268 -> 0 bytes .../index/cmd/testdata/ledgers/1410242 | Bin 6556 -> 0 bytes .../index/cmd/testdata/ledgers/1410243 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410244 | Bin 7236 -> 0 bytes .../index/cmd/testdata/ledgers/1410245 | Bin 7088 -> 0 bytes .../index/cmd/testdata/ledgers/1410246 | Bin 7160 -> 0 bytes .../index/cmd/testdata/ledgers/1410247 | Bin 4728 -> 0 bytes .../index/cmd/testdata/ledgers/1410248 | Bin 5928 -> 0 bytes .../index/cmd/testdata/ledgers/1410249 | Bin 5132 -> 0 bytes .../index/cmd/testdata/ledgers/1410250 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410251 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410252 | Bin 4148 -> 0 bytes .../index/cmd/testdata/ledgers/1410253 | Bin 5088 -> 0 bytes .../index/cmd/testdata/ledgers/1410254 | Bin 4932 -> 0 bytes .../index/cmd/testdata/ledgers/1410255 | Bin 6208 -> 0 bytes .../index/cmd/testdata/ledgers/1410256 | Bin 2864 -> 0 bytes .../index/cmd/testdata/ledgers/1410257 | Bin 3892 -> 0 bytes .../index/cmd/testdata/ledgers/1410258 | Bin 1528 -> 0 bytes .../index/cmd/testdata/ledgers/1410259 | Bin 2648 -> 0 bytes .../index/cmd/testdata/ledgers/1410260 | Bin 2736 -> 0 bytes .../index/cmd/testdata/ledgers/1410261 | Bin 2428 -> 0 bytes .../index/cmd/testdata/ledgers/1410262 | Bin 2428 -> 0 bytes .../index/cmd/testdata/ledgers/1410263 | Bin 2428 -> 0 bytes .../index/cmd/testdata/ledgers/1410264 | Bin 3588 -> 0 bytes .../index/cmd/testdata/ledgers/1410265 | Bin 1476 -> 0 bytes .../index/cmd/testdata/ledgers/1410266 | Bin 2684 -> 0 bytes .../index/cmd/testdata/ledgers/1410267 | Bin 2764 -> 0 bytes .../index/cmd/testdata/ledgers/1410268 | Bin 3876 -> 0 bytes .../index/cmd/testdata/ledgers/1410269 | Bin 7072 -> 0 bytes .../index/cmd/testdata/ledgers/1410270 | Bin 6052 -> 0 bytes .../index/cmd/testdata/ledgers/1410271 | Bin 6060 -> 0 bytes .../index/cmd/testdata/ledgers/1410272 | Bin 6276 -> 0 bytes .../index/cmd/testdata/ledgers/1410273 | Bin 4864 -> 0 bytes .../index/cmd/testdata/ledgers/1410274 | Bin 3976 -> 0 bytes .../index/cmd/testdata/ledgers/1410275 | Bin 3896 -> 0 bytes .../index/cmd/testdata/ledgers/1410276 | Bin 3896 -> 0 bytes .../index/cmd/testdata/ledgers/1410277 | Bin 5352 -> 0 bytes .../index/cmd/testdata/ledgers/1410278 | Bin 4076 -> 0 bytes .../index/cmd/testdata/ledgers/1410279 | Bin 4876 -> 0 bytes .../index/cmd/testdata/ledgers/1410280 | Bin 6020 -> 0 bytes .../index/cmd/testdata/ledgers/1410281 | Bin 4100 -> 0 bytes .../index/cmd/testdata/ledgers/1410282 | Bin 2684 -> 0 bytes .../index/cmd/testdata/ledgers/1410283 | Bin 2596 -> 0 bytes .../index/cmd/testdata/ledgers/1410284 | Bin 1476 -> 0 bytes .../index/cmd/testdata/ledgers/1410285 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410286 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410287 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410288 | Bin 3692 -> 0 bytes .../index/cmd/testdata/ledgers/1410289 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410290 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410291 | Bin 3772 -> 0 bytes .../index/cmd/testdata/ledgers/1410292 | Bin 2708 -> 0 bytes .../index/cmd/testdata/ledgers/1410293 | Bin 6368 -> 0 bytes .../index/cmd/testdata/ledgers/1410294 | Bin 3920 -> 0 bytes .../index/cmd/testdata/ledgers/1410295 | Bin 4736 -> 0 bytes .../index/cmd/testdata/ledgers/1410296 | Bin 4076 -> 0 bytes .../index/cmd/testdata/ledgers/1410297 | Bin 2664 -> 0 bytes .../index/cmd/testdata/ledgers/1410298 | Bin 4080 -> 0 bytes .../index/cmd/testdata/ledgers/1410299 | Bin 4828 -> 0 bytes .../index/cmd/testdata/ledgers/1410300 | Bin 4148 -> 0 bytes .../index/cmd/testdata/ledgers/1410301 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410302 | Bin 5088 -> 0 bytes .../index/cmd/testdata/ledgers/1410303 | Bin 6076 -> 0 bytes .../index/cmd/testdata/ledgers/1410304 | Bin 6376 -> 0 bytes .../index/cmd/testdata/ledgers/1410305 | Bin 8292 -> 0 bytes .../index/cmd/testdata/ledgers/1410306 | Bin 6692 -> 0 bytes .../index/cmd/testdata/ledgers/1410307 | Bin 5688 -> 0 bytes .../index/cmd/testdata/ledgers/1410308 | Bin 3228 -> 0 bytes .../index/cmd/testdata/ledgers/1410309 | Bin 2428 -> 0 bytes .../index/cmd/testdata/ledgers/1410310 | Bin 3636 -> 0 bytes .../index/cmd/testdata/ledgers/1410311 | Bin 1472 -> 0 bytes .../index/cmd/testdata/ledgers/1410312 | Bin 1472 -> 0 bytes .../index/cmd/testdata/ledgers/1410313 | Bin 520 -> 0 bytes .../index/cmd/testdata/ledgers/1410314 | Bin 1596 -> 0 bytes .../index/cmd/testdata/ledgers/1410315 | Bin 1728 -> 0 bytes .../index/cmd/testdata/ledgers/1410316 | Bin 2764 -> 0 bytes .../index/cmd/testdata/ledgers/1410317 | Bin 1476 -> 0 bytes .../index/cmd/testdata/ledgers/1410318 | Bin 4892 -> 0 bytes .../index/cmd/testdata/ledgers/1410319 | Bin 3596 -> 0 bytes .../index/cmd/testdata/ledgers/1410320 | Bin 4884 -> 0 bytes .../index/cmd/testdata/ledgers/1410321 | Bin 6140 -> 0 bytes .../index/cmd/testdata/ledgers/1410322 | Bin 4628 -> 0 bytes .../index/cmd/testdata/ledgers/1410323 | Bin 5088 -> 0 bytes .../index/cmd/testdata/ledgers/1410324 | Bin 3620 -> 0 bytes .../index/cmd/testdata/ledgers/1410325 | Bin 5032 -> 0 bytes .../index/cmd/testdata/ledgers/1410326 | Bin 5648 -> 0 bytes .../index/cmd/testdata/ledgers/1410327 | Bin 7596 -> 0 bytes .../index/cmd/testdata/ledgers/1410328 | Bin 4796 -> 0 bytes .../index/cmd/testdata/ledgers/1410329 | Bin 4244 -> 0 bytes .../index/cmd/testdata/ledgers/1410330 | Bin 3036 -> 0 bytes .../index/cmd/testdata/ledgers/1410331 | Bin 3124 -> 0 bytes .../index/cmd/testdata/ledgers/1410332 | Bin 5040 -> 0 bytes .../index/cmd/testdata/ledgers/1410333 | Bin 3608 -> 0 bytes .../index/cmd/testdata/ledgers/1410334 | Bin 3660 -> 0 bytes .../index/cmd/testdata/ledgers/1410335 | Bin 4236 -> 0 bytes .../index/cmd/testdata/ledgers/1410336 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410337 | Bin 4768 -> 0 bytes .../index/cmd/testdata/ledgers/1410338 | Bin 2484 -> 0 bytes .../index/cmd/testdata/ledgers/1410339 | Bin 3772 -> 0 bytes .../index/cmd/testdata/ledgers/1410340 | Bin 1476 -> 0 bytes .../index/cmd/testdata/ledgers/1410341 | Bin 3548 -> 0 bytes .../index/cmd/testdata/ledgers/1410342 | Bin 2428 -> 0 bytes .../index/cmd/testdata/ledgers/1410343 | Bin 3636 -> 0 bytes .../index/cmd/testdata/ledgers/1410344 | Bin 2428 -> 0 bytes .../index/cmd/testdata/ledgers/1410345 | Bin 2764 -> 0 bytes .../index/cmd/testdata/ledgers/1410346 | Bin 3876 -> 0 bytes .../index/cmd/testdata/ledgers/1410347 | Bin 3700 -> 0 bytes .../index/cmd/testdata/ledgers/1410348 | Bin 5252 -> 0 bytes .../index/cmd/testdata/ledgers/1410349 | Bin 2888 -> 0 bytes .../index/cmd/testdata/ledgers/1410350 | Bin 5600 -> 0 bytes .../index/cmd/testdata/ledgers/1410351 | Bin 3280 -> 0 bytes .../index/cmd/testdata/ledgers/1410352 | Bin 3936 -> 0 bytes .../index/cmd/testdata/ledgers/1410353 | Bin 6092 -> 0 bytes .../index/cmd/testdata/ledgers/1410354 | Bin 4708 -> 0 bytes .../index/cmd/testdata/ledgers/1410355 | Bin 6060 -> 0 bytes .../index/cmd/testdata/ledgers/1410356 | Bin 5804 -> 0 bytes .../index/cmd/testdata/ledgers/1410357 | Bin 4728 -> 0 bytes .../index/cmd/testdata/ledgers/1410358 | Bin 4808 -> 0 bytes .../index/cmd/testdata/ledgers/1410359 | Bin 6084 -> 0 bytes .../index/cmd/testdata/ledgers/1410360 | Bin 4920 -> 0 bytes .../index/cmd/testdata/ledgers/1410361 | Bin 3844 -> 0 bytes .../index/cmd/testdata/ledgers/1410362 | Bin 5436 -> 0 bytes .../index/cmd/testdata/ledgers/1410363 | Bin 4080 -> 0 bytes .../index/cmd/testdata/ledgers/1410364 | Bin 6252 -> 0 bytes .../index/cmd/testdata/ledgers/1410365 | Bin 5000 -> 0 bytes .../index/cmd/testdata/ledgers/1410366 | Bin 4996 -> 0 bytes .../index/cmd/testdata/ledgers/1410367 | Bin 6884 -> 0 bytes .../index/cmd/testdata/regenerate.sh | 3 - exp/lighthorizon/index/connect.go | 68 --- exp/lighthorizon/index/mock_store.go | 78 --- exp/lighthorizon/index/modules.go | 314 ------------ exp/lighthorizon/index/store.go | 377 -------------- exp/lighthorizon/index/types/bitmap.go | 367 -------------- exp/lighthorizon/index/types/bitmap_test.go | 382 -------------- exp/lighthorizon/index/types/trie.go | 345 ------------- exp/lighthorizon/index/types/trie_test.go | 297 ----------- exp/lighthorizon/ingester/ingester.go | 55 -- exp/lighthorizon/ingester/main.go | 87 ---- exp/lighthorizon/ingester/mock_ingester.go | 44 -- .../ingester/parallel_ingester.go | 141 ------ exp/lighthorizon/ingester/participants.go | 35 -- exp/lighthorizon/main.go | 183 ------- exp/lighthorizon/services/cursor.go | 102 ---- exp/lighthorizon/services/cursor_test.go | 96 ---- exp/lighthorizon/services/main.go | 216 -------- exp/lighthorizon/services/main_test.go | 250 --------- exp/lighthorizon/services/mock_services.go | 32 -- exp/lighthorizon/services/operations.go | 90 ---- exp/lighthorizon/services/transactions.go | 76 --- exp/lighthorizon/tools/cache.go | 270 ---------- exp/lighthorizon/tools/index.go | 356 ------------- exp/lighthorizon/tools/index_test.go | 58 --- gxdr/xdr_generated.go | 238 +-------- .../ledgerbackend/history_archive_backend.go | 51 -- metaarchive/main.go | 62 --- xdr/xdr_generated.go | 478 ------------------ 424 files changed, 2 insertions(+), 11190 deletions(-) delete mode 100644 exp/lighthorizon/actions/accounts.go delete mode 100644 exp/lighthorizon/actions/accounts_test.go delete mode 100644 exp/lighthorizon/actions/apidocs.go delete mode 100644 exp/lighthorizon/actions/main.go delete mode 100644 exp/lighthorizon/actions/problem.go delete mode 100644 exp/lighthorizon/actions/root.go delete mode 100644 exp/lighthorizon/actions/static/api_docs.yml delete mode 100644 exp/lighthorizon/adapters/account_merge.go delete mode 100644 exp/lighthorizon/adapters/allow_trust.go delete mode 100644 exp/lighthorizon/adapters/begin_sponsoring_future_reserves.go delete mode 100644 exp/lighthorizon/adapters/bump_sequence.go delete mode 100644 exp/lighthorizon/adapters/change_trust.go delete mode 100644 exp/lighthorizon/adapters/claim_claimable_balance.go delete mode 100644 exp/lighthorizon/adapters/clawback.go delete mode 100644 exp/lighthorizon/adapters/clawback_claimable_balance.go delete mode 100644 exp/lighthorizon/adapters/create_account.go delete mode 100644 exp/lighthorizon/adapters/create_claimable_balance.go delete mode 100644 exp/lighthorizon/adapters/create_passive_sell_offer.go delete mode 100644 exp/lighthorizon/adapters/end_sponsoring_future_reserves.go delete mode 100644 exp/lighthorizon/adapters/inflation.go delete mode 100644 exp/lighthorizon/adapters/liquidity_pool_deposit.go delete mode 100644 exp/lighthorizon/adapters/liquidity_pool_withdraw.go delete mode 100644 exp/lighthorizon/adapters/manage_buy_offer.go delete mode 100644 exp/lighthorizon/adapters/manage_data.go delete mode 100644 exp/lighthorizon/adapters/manage_sell_offer.go delete mode 100644 exp/lighthorizon/adapters/operation.go delete mode 100644 exp/lighthorizon/adapters/path_payment_strict_receive.go delete mode 100644 exp/lighthorizon/adapters/path_payment_strict_send.go delete mode 100644 exp/lighthorizon/adapters/payment.go delete mode 100644 exp/lighthorizon/adapters/revoke_sponsorship.go delete mode 100644 exp/lighthorizon/adapters/set_options.go delete mode 100644 exp/lighthorizon/adapters/set_trust_line_flags.go delete mode 100644 exp/lighthorizon/adapters/testdata/transactions.json delete mode 100644 exp/lighthorizon/adapters/transaction.go delete mode 100644 exp/lighthorizon/adapters/transaction_test.go delete mode 100644 exp/lighthorizon/build/README.md delete mode 100755 exp/lighthorizon/build/build.sh delete mode 100644 exp/lighthorizon/build/index-batch/Dockerfile delete mode 100644 exp/lighthorizon/build/index-batch/README.md delete mode 100644 exp/lighthorizon/build/index-batch/start delete mode 100644 exp/lighthorizon/build/index-single/Dockerfile delete mode 100644 exp/lighthorizon/build/k8s/ledgerexporter.yml delete mode 100644 exp/lighthorizon/build/k8s/lighthorizon_batch_map_job.yml delete mode 100644 exp/lighthorizon/build/k8s/lighthorizon_batch_reduce_job.yml delete mode 100644 exp/lighthorizon/build/k8s/lighthorizon_index.yml delete mode 100644 exp/lighthorizon/build/k8s/lighthorizon_web.yml delete mode 100644 exp/lighthorizon/build/ledgerexporter/Dockerfile delete mode 100644 exp/lighthorizon/build/ledgerexporter/README.md delete mode 100644 exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg delete mode 100644 exp/lighthorizon/build/ledgerexporter/captive-core-testnet.cfg delete mode 100644 exp/lighthorizon/build/ledgerexporter/start delete mode 100644 exp/lighthorizon/build/web/Dockerfile delete mode 100644 exp/lighthorizon/common/operation.go delete mode 100644 exp/lighthorizon/common/transaction.go delete mode 100644 exp/lighthorizon/http.go delete mode 100644 exp/lighthorizon/http_test.go delete mode 100644 exp/lighthorizon/index/Makefile delete mode 100644 exp/lighthorizon/index/backend/backend.go delete mode 100644 exp/lighthorizon/index/backend/file.go delete mode 100644 exp/lighthorizon/index/backend/file_test.go delete mode 100644 exp/lighthorizon/index/backend/gzip.go delete mode 100644 exp/lighthorizon/index/backend/gzip_test.go delete mode 100644 exp/lighthorizon/index/backend/parallel_flush.go delete mode 100644 exp/lighthorizon/index/backend/s3.go delete mode 100644 exp/lighthorizon/index/builder.go delete mode 100644 exp/lighthorizon/index/cmd/batch/doc.go delete mode 100644 exp/lighthorizon/index/cmd/batch/map/main.go delete mode 100644 exp/lighthorizon/index/cmd/batch/reduce/main.go delete mode 100755 exp/lighthorizon/index/cmd/map.sh delete mode 100644 exp/lighthorizon/index/cmd/mapreduce_test.go delete mode 100755 exp/lighthorizon/index/cmd/reduce.sh delete mode 100644 exp/lighthorizon/index/cmd/single/main.go delete mode 100644 exp/lighthorizon/index/cmd/single_test.go delete mode 100644 exp/lighthorizon/index/cmd/testdata/latest delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410048 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410049 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410050 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410051 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410052 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410053 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410054 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410055 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410056 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410057 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410058 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410059 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410060 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410061 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410062 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410063 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410064 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410065 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410066 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410067 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410068 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410069 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410070 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410071 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410072 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410073 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410074 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410075 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410076 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410077 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410078 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410079 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410080 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410081 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410082 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410083 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410084 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410085 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410086 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410087 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410088 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410089 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410090 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410091 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410092 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410093 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410094 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410095 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410096 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410097 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410098 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410099 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410100 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410101 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410102 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410103 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410104 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410105 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410106 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410107 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410108 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410109 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410110 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410111 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410112 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410113 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410114 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410115 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410116 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410117 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410118 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410119 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410120 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410121 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410122 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410123 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410124 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410125 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410126 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410127 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410128 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410129 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410130 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410131 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410132 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410133 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410134 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410135 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410136 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410137 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410138 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410139 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410140 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410141 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410142 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410143 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410144 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410145 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410146 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410147 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410148 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410149 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410150 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410151 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410152 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410153 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410154 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410155 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410156 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410157 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410158 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410159 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410160 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410161 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410162 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410163 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410164 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410165 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410166 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410167 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410168 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410169 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410170 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410171 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410172 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410173 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410174 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410175 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410176 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410177 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410178 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410179 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410180 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410181 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410182 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410183 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410184 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410185 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410186 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410187 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410188 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410189 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410190 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410191 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410192 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410193 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410194 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410195 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410196 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410197 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410198 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410199 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410200 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410201 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410202 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410203 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410204 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410205 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410206 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410207 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410208 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410209 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410210 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410211 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410212 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410213 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410214 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410215 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410216 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410217 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410218 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410219 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410220 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410221 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410222 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410223 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410224 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410225 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410226 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410227 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410228 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410229 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410230 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410231 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410232 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410233 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410234 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410235 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410236 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410237 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410238 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410239 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410240 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410241 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410242 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410243 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410244 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410245 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410246 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410247 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410248 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410249 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410250 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410251 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410252 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410253 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410254 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410255 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410256 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410257 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410258 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410259 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410260 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410261 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410262 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410263 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410264 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410265 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410266 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410267 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410268 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410269 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410270 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410271 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410272 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410273 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410274 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410275 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410276 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410277 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410278 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410279 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410280 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410281 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410282 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410283 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410284 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410285 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410286 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410287 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410288 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410289 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410290 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410291 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410292 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410293 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410294 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410295 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410296 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410297 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410298 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410299 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410300 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410301 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410302 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410303 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410304 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410305 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410306 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410307 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410308 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410309 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410310 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410311 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410312 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410313 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410314 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410315 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410316 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410317 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410318 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410319 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410320 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410321 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410322 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410323 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410324 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410325 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410326 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410327 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410328 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410329 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410330 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410331 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410332 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410333 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410334 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410335 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410336 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410337 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410338 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410339 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410340 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410341 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410342 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410343 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410344 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410345 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410346 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410347 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410348 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410349 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410350 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410351 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410352 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410353 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410354 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410355 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410356 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410357 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410358 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410359 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410360 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410361 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410362 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410363 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410364 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410365 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410366 delete mode 100644 exp/lighthorizon/index/cmd/testdata/ledgers/1410367 delete mode 100644 exp/lighthorizon/index/cmd/testdata/regenerate.sh delete mode 100644 exp/lighthorizon/index/connect.go delete mode 100644 exp/lighthorizon/index/mock_store.go delete mode 100644 exp/lighthorizon/index/modules.go delete mode 100644 exp/lighthorizon/index/store.go delete mode 100644 exp/lighthorizon/index/types/bitmap.go delete mode 100644 exp/lighthorizon/index/types/bitmap_test.go delete mode 100644 exp/lighthorizon/index/types/trie.go delete mode 100644 exp/lighthorizon/index/types/trie_test.go delete mode 100644 exp/lighthorizon/ingester/ingester.go delete mode 100644 exp/lighthorizon/ingester/main.go delete mode 100644 exp/lighthorizon/ingester/mock_ingester.go delete mode 100644 exp/lighthorizon/ingester/parallel_ingester.go delete mode 100644 exp/lighthorizon/ingester/participants.go delete mode 100644 exp/lighthorizon/main.go delete mode 100644 exp/lighthorizon/services/cursor.go delete mode 100644 exp/lighthorizon/services/cursor_test.go delete mode 100644 exp/lighthorizon/services/main.go delete mode 100644 exp/lighthorizon/services/main_test.go delete mode 100644 exp/lighthorizon/services/mock_services.go delete mode 100644 exp/lighthorizon/services/operations.go delete mode 100644 exp/lighthorizon/services/transactions.go delete mode 100644 exp/lighthorizon/tools/cache.go delete mode 100644 exp/lighthorizon/tools/index.go delete mode 100644 exp/lighthorizon/tools/index_test.go delete mode 100644 ingest/ledgerbackend/history_archive_backend.go delete mode 100644 metaarchive/main.go diff --git a/Makefile b/Makefile index 07037315e4..69d46f68c3 100644 --- a/Makefile +++ b/Makefile @@ -14,8 +14,7 @@ xdr/Stellar-contract.x \ xdr/Stellar-internal.x \ xdr/Stellar-contract-config-setting.x -XDRS = $(DOWNLOADABLE_XDRS) xdr/Stellar-lighthorizon.x \ - xdr/Stellar-exporter.x +XDRS = $(DOWNLOADABLE_XDRS) xdr/Stellar-exporter.x XDRGEN_COMMIT=e2cac557162d99b12ae73b846cf3d5bfe16636de diff --git a/exp/lighthorizon/actions/accounts.go b/exp/lighthorizon/actions/accounts.go deleted file mode 100644 index 86673afa68..0000000000 --- a/exp/lighthorizon/actions/accounts.go +++ /dev/null @@ -1,142 +0,0 @@ -package actions - -import ( - "errors" - "net/http" - "os" - "strconv" - - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" - - "github.com/stellar/go/exp/lighthorizon/adapters" - "github.com/stellar/go/exp/lighthorizon/services" - hProtocol "github.com/stellar/go/protocols/horizon" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/render/hal" - supportProblem "github.com/stellar/go/support/render/problem" - "github.com/stellar/go/toid" -) - -const ( - urlAccountId = "account_id" -) - -func accountRequestParams(w http.ResponseWriter, r *http.Request) (string, pagination, error) { - var accountId string - var accountErr bool - - if accountId, accountErr = getURLParam(r, urlAccountId); !accountErr { - return "", pagination{}, errors.New("unable to find account_id in url path") - } - - paginate, err := paging(r) - if err != nil { - return "", pagination{}, err - } - - if paginate.Cursor < 1 { - paginate.Cursor = toid.New(1, 1, 1).ToInt64() - } - - if paginate.Limit == 0 { - paginate.Limit = 10 - } - - return accountId, paginate, nil -} - -func NewTXByAccountHandler(lightHorizon services.LightHorizon) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - var accountId string - var paginate pagination - var err error - - if accountId, paginate, err = accountRequestParams(w, r); err != nil { - errorMsg := supportProblem.MakeInvalidFieldProblem("account_id", err) - sendErrorResponse(r.Context(), w, *errorMsg) - return - } - - page := hal.Page{ - Cursor: strconv.FormatInt(paginate.Cursor, 10), - Order: string(paginate.Order), - Limit: uint64(paginate.Limit), - } - page.Init() - page.FullURL = r.URL - - txns, err := lightHorizon.Transactions.GetTransactionsByAccount(ctx, paginate.Cursor, paginate.Limit, accountId) - if err != nil { - log.Error(err) - if os.IsNotExist(err) { - sendErrorResponse(r.Context(), w, supportProblem.NotFound) - } else if err != nil { - sendErrorResponse(r.Context(), w, supportProblem.ServerError) - } - return - } - - encoder := xdr.NewEncodingBuffer() - for _, txn := range txns { - var response hProtocol.Transaction - response, err = adapters.PopulateTransaction(r.URL, &txn, encoder) - if err != nil { - log.Error(err) - sendErrorResponse(r.Context(), w, supportProblem.ServerError) - return - } - - page.Add(response) - } - - page.PopulateLinks() - sendPageResponse(r.Context(), w, page) - } -} - -func NewOpsByAccountHandler(lightHorizon services.LightHorizon) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() - var accountId string - var paginate pagination - var err error - - if accountId, paginate, err = accountRequestParams(w, r); err != nil { - errorMsg := supportProblem.MakeInvalidFieldProblem("account_id", err) - sendErrorResponse(r.Context(), w, *errorMsg) - return - } - - page := hal.Page{ - Cursor: strconv.FormatInt(paginate.Cursor, 10), - Order: string(paginate.Order), - Limit: uint64(paginate.Limit), - } - page.Init() - page.FullURL = r.URL - - ops, err := lightHorizon.Operations.GetOperationsByAccount(ctx, paginate.Cursor, paginate.Limit, accountId) - if err != nil { - log.Error(err) - sendErrorResponse(r.Context(), w, supportProblem.ServerError) - return - } - - for _, op := range ops { - var response operations.Operation - response, err = adapters.PopulateOperation(r, &op) - if err != nil { - log.Error(err) - sendErrorResponse(r.Context(), w, supportProblem.ServerError) - return - } - - page.Add(response) - } - - page.PopulateLinks() - sendPageResponse(r.Context(), w, page) - } -} diff --git a/exp/lighthorizon/actions/accounts_test.go b/exp/lighthorizon/actions/accounts_test.go deleted file mode 100644 index 40576fb7e4..0000000000 --- a/exp/lighthorizon/actions/accounts_test.go +++ /dev/null @@ -1,191 +0,0 @@ -package actions - -import ( - "context" - "encoding/json" - "errors" - "io/ioutil" - "net/http" - "net/http/httptest" - "net/url" - "testing" - - "github.com/go-chi/chi" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/exp/lighthorizon/services" - "github.com/stellar/go/support/render/problem" -) - -func setupTest() { - problem.RegisterHost("") -} - -func TestTxByAccountMissingParamError(t *testing.T) { - setupTest() - recorder := httptest.NewRecorder() - request := buildHttpRequest( - t, - map[string]string{}, - map[string]string{}, - ) - - mockOperationService := &services.MockOperationService{} - mockTransactionService := &services.MockTransactionService{} - - lh := services.LightHorizon{ - Operations: mockOperationService, - Transactions: mockTransactionService, - } - - handler := NewTXByAccountHandler(lh) - handler(recorder, request) - - resp := recorder.Result() - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - - raw, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var problem problem.P - err = json.Unmarshal(raw, &problem) - assert.NoError(t, err) - assert.Equal(t, "Bad Request", problem.Title) - assert.Equal(t, "bad_request", problem.Type) - assert.Equal(t, "account_id", problem.Extras["invalid_field"]) - assert.Equal(t, "The request you sent was invalid in some way.", problem.Detail) - assert.Equal(t, "unable to find account_id in url path", problem.Extras["reason"]) -} - -func TestTxByAccountServerError(t *testing.T) { - setupTest() - recorder := httptest.NewRecorder() - pathParams := make(map[string]string) - pathParams["account_id"] = "G1234" - request := buildHttpRequest( - t, - map[string]string{}, - pathParams, - ) - - mockOperationService := &services.MockOperationService{} - mockTransactionService := &services.MockTransactionService{} - mockTransactionService.On("GetTransactionsByAccount", mock.Anything, mock.Anything, mock.Anything, "G1234").Return([]common.Transaction{}, errors.New("not good")) - - lh := services.LightHorizon{ - Operations: mockOperationService, - Transactions: mockTransactionService, - } - - handler := NewTXByAccountHandler(lh) - handler(recorder, request) - - resp := recorder.Result() - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - - raw, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var problem problem.P - err = json.Unmarshal(raw, &problem) - assert.NoError(t, err) - assert.Equal(t, "Internal Server Error", problem.Title) - assert.Equal(t, "server_error", problem.Type) -} - -func TestOpsByAccountMissingParamError(t *testing.T) { - setupTest() - recorder := httptest.NewRecorder() - request := buildHttpRequest( - t, - map[string]string{}, - map[string]string{}, - ) - - mockOperationService := &services.MockOperationService{} - mockTransactionService := &services.MockTransactionService{} - - lh := services.LightHorizon{ - Operations: mockOperationService, - Transactions: mockTransactionService, - } - - handler := NewOpsByAccountHandler(lh) - handler(recorder, request) - - resp := recorder.Result() - assert.Equal(t, http.StatusBadRequest, resp.StatusCode) - - raw, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var problem problem.P - err = json.Unmarshal(raw, &problem) - assert.NoError(t, err) - assert.Equal(t, "Bad Request", problem.Title) - assert.Equal(t, "bad_request", problem.Type) - assert.Equal(t, "account_id", problem.Extras["invalid_field"]) - assert.Equal(t, "The request you sent was invalid in some way.", problem.Detail) - assert.Equal(t, "unable to find account_id in url path", problem.Extras["reason"]) -} - -func TestOpsByAccountServerError(t *testing.T) { - setupTest() - recorder := httptest.NewRecorder() - pathParams := make(map[string]string) - pathParams["account_id"] = "G1234" - request := buildHttpRequest( - t, - map[string]string{}, - pathParams, - ) - - mockOperationService := &services.MockOperationService{} - mockTransactionService := &services.MockTransactionService{} - mockOperationService.On("GetOperationsByAccount", mock.Anything, mock.Anything, mock.Anything, "G1234").Return([]common.Operation{}, errors.New("not good")) - - lh := services.LightHorizon{ - Operations: mockOperationService, - Transactions: mockTransactionService, - } - - handler := NewOpsByAccountHandler(lh) - handler(recorder, request) - - resp := recorder.Result() - assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) - - raw, err := ioutil.ReadAll(resp.Body) - assert.NoError(t, err) - - var problem problem.P - err = json.Unmarshal(raw, &problem) - assert.NoError(t, err) - assert.Equal(t, "Internal Server Error", problem.Title) - assert.Equal(t, "server_error", problem.Type) -} - -func buildHttpRequest( - t *testing.T, - queryParams map[string]string, - routeParams map[string]string, -) *http.Request { - request, err := http.NewRequest("GET", "/", nil) - require.NoError(t, err) - - query := url.Values{} - for key, value := range queryParams { - query.Set(key, value) - } - request.URL.RawQuery = query.Encode() - - chiRouteContext := chi.NewRouteContext() - for key, value := range routeParams { - chiRouteContext.URLParams.Add(key, value) - } - ctx := context.WithValue(context.Background(), chi.RouteCtxKey, chiRouteContext) - return request.WithContext(ctx) -} diff --git a/exp/lighthorizon/actions/apidocs.go b/exp/lighthorizon/actions/apidocs.go deleted file mode 100644 index 713c4054fa..0000000000 --- a/exp/lighthorizon/actions/apidocs.go +++ /dev/null @@ -1,26 +0,0 @@ -package actions - -import ( - supportProblem "github.com/stellar/go/support/render/problem" - "net/http" -) - -func ApiDocs() func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - r.URL.Scheme = "http" - r.URL.Host = "localhost:8080" - - if r.Method != "GET" { - sendErrorResponse(r.Context(), w, supportProblem.BadRequest) - return - } - - p, err := staticFiles.ReadFile("static/api_docs.yml") - if err != nil { - w.WriteHeader(http.StatusNotFound) - return - } - w.Header().Set("Content-Type", "application/openapi+yaml") - w.Write(p) - } -} diff --git a/exp/lighthorizon/actions/main.go b/exp/lighthorizon/actions/main.go deleted file mode 100644 index 01769682b5..0000000000 --- a/exp/lighthorizon/actions/main.go +++ /dev/null @@ -1,124 +0,0 @@ -package actions - -import ( - "context" - "embed" - "encoding/json" - "net/http" - "net/url" - "strconv" - - "github.com/go-chi/chi" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promauto" - "github.com/stellar/go/support/log" - "github.com/stellar/go/support/render/hal" - supportProblem "github.com/stellar/go/support/render/problem" -) - -var ( - //go:embed static - staticFiles embed.FS - //lint:ignore U1000 temporary - requestCount = promauto.NewCounter(prometheus.CounterOpts{ - Name: "horizon_lite_request_count", - Help: "How many requests have occurred?", - }) - //lint:ignore U1000 temporary - requestTime = promauto.NewHistogram(prometheus.HistogramOpts{ - Name: "horizon_lite_request_duration", - Help: "How long do requests take?", - Buckets: append( - prometheus.LinearBuckets(0, 50, 20), - prometheus.LinearBuckets(1000, 1000, 8)..., - ), - }) -) - -type order string - -const ( - orderAsc order = "asc" - orderDesc order = "desc" -) - -type pagination struct { - Limit uint64 - Cursor int64 - Order order -} - -func sendPageResponse(ctx context.Context, w http.ResponseWriter, page hal.Page) { - w.Header().Set("Content-Type", "application/hal+json; charset=utf-8") - encoder := json.NewEncoder(w) - encoder.SetIndent("", " ") - err := encoder.Encode(page) - if err != nil { - log.Error(err) - sendErrorResponse(ctx, w, supportProblem.ServerError) - } -} - -func sendErrorResponse(ctx context.Context, w http.ResponseWriter, problem supportProblem.P) { - supportProblem.Render(ctx, w, problem) -} - -func requestUnaryParam(r *http.Request, paramName string) (string, error) { - query, err := url.ParseQuery(r.URL.RawQuery) - if err != nil { - return "", err - } - return query.Get(paramName), nil -} - -func paging(r *http.Request) (pagination, error) { - paginate := pagination{ - Order: orderAsc, - } - - if cursorRequested, err := requestUnaryParam(r, "cursor"); err != nil { - return pagination{}, err - } else if cursorRequested != "" { - paginate.Cursor, err = strconv.ParseInt(cursorRequested, 10, 64) - if err != nil { - return pagination{}, err - } - } - - if limitRequested, err := requestUnaryParam(r, "limit"); err != nil { - return pagination{}, err - } else if limitRequested != "" { - paginate.Limit, err = strconv.ParseUint(limitRequested, 10, 64) - if err != nil { - return pagination{}, err - } - } - - if orderRequested, err := requestUnaryParam(r, "order"); err != nil { - return pagination{}, err - } else if orderRequested != "" && orderRequested == string(orderDesc) { - paginate.Order = orderDesc - } - - return paginate, nil -} - -func getURLParam(r *http.Request, key string) (string, bool) { - rctx := chi.RouteContext(r.Context()) - - if rctx == nil { - return "", false - } - - if len(rctx.URLParams.Keys) != len(rctx.URLParams.Values) { - return "", false - } - - for k := len(rctx.URLParams.Keys) - 1; k >= 0; k-- { - if rctx.URLParams.Keys[k] == key { - return rctx.URLParams.Values[k], true - } - } - - return "", false -} diff --git a/exp/lighthorizon/actions/problem.go b/exp/lighthorizon/actions/problem.go deleted file mode 100644 index cd82cfb1e8..0000000000 --- a/exp/lighthorizon/actions/problem.go +++ /dev/null @@ -1,94 +0,0 @@ -package actions - -import ( - "net/http" - - "github.com/stellar/go/support/render/problem" -) - -// Well-known and reused problems below: -// inspired by similar default established in horizon - services/horizon/internal/render/problem/problem.go -var ( - - // ClientDisconnected, represented by a non-standard HTTP status code of 499, which was introduced by - // nginix.org(https://www.nginx.com/resources/wiki/extending/api/http/) as a way to capture this state. Use it as a shortcut - // in your actions. - ClientDisconnected = problem.P{ - Type: "client_disconnected", - Title: "Client Disconnected", - Status: 499, - Detail: "The client has closed the connection.", - } - - // ServiceUnavailable is a well-known problem type. Use it as a shortcut - // in your actions. - ServiceUnavailable = problem.P{ - Type: "service_unavailable", - Title: "Service Unavailable", - Status: http.StatusServiceUnavailable, - Detail: "The request cannot be serviced at this time.", - } - - // RateLimitExceeded is a well-known problem type. Use it as a shortcut - // in your actions. - RateLimitExceeded = problem.P{ - Type: "rate_limit_exceeded", - Title: "Rate Limit Exceeded", - Status: 429, - Detail: "The rate limit for the requesting IP address is over its alloted " + - "limit. The allowed limit and requests left per time period are " + - "communicated to clients via the http response headers 'X-RateLimit-*' " + - "headers.", - } - - // NotImplemented is a well-known problem type. Use it as a shortcut - // in your actions. - NotImplemented = problem.P{ - Type: "not_implemented", - Title: "Resource Not Yet Implemented", - Status: http.StatusNotFound, - Detail: "While the requested URL is expected to eventually point to a " + - "valid resource, the work to implement the resource has not yet " + - "been completed.", - } - - // NotAcceptable is a well-known problem type. Use it as a shortcut - // in your actions. - NotAcceptable = problem.P{ - Type: "not_acceptable", - Title: "An acceptable response content-type could not be provided for " + - "this request", - Status: http.StatusNotAcceptable, - } - - // ServerOverCapacity is a well-known problem type. Use it as a shortcut - // in your actions. - ServerOverCapacity = problem.P{ - Type: "server_over_capacity", - Title: "Server Over Capacity", - Status: http.StatusServiceUnavailable, - Detail: "This horizon server is currently overloaded. Please wait for " + - "several minutes before trying your request again.", - } - - // Timeout is a well-known problem type. Use it as a shortcut - // in your actions. - Timeout = problem.P{ - Type: "timeout", - Title: "Timeout", - Status: http.StatusGatewayTimeout, - Detail: "Your request timed out before completing. Please try your " + - "request again. If you are submitting a transaction make sure you are " + - "sending exactly the same transaction (with the same sequence number).", - } - - // UnsupportedMediaType is a well-known problem type. Use it as a shortcut - // in your actions. - UnsupportedMediaType = problem.P{ - Type: "unsupported_media_type", - Title: "Unsupported Media Type", - Status: http.StatusUnsupportedMediaType, - Detail: "The request has an unsupported content type. Presently, the " + - "only supported content type is application/x-www-form-urlencoded.", - } -) diff --git a/exp/lighthorizon/actions/root.go b/exp/lighthorizon/actions/root.go deleted file mode 100644 index 3dfa4341a0..0000000000 --- a/exp/lighthorizon/actions/root.go +++ /dev/null @@ -1,29 +0,0 @@ -package actions - -import ( - "encoding/json" - "net/http" - - "github.com/stellar/go/support/log" - supportProblem "github.com/stellar/go/support/render/problem" -) - -type RootResponse struct { - Version string `json:"version"` - LedgerSource string `json:"ledger_source"` - IndexSource string `json:"index_source"` - LatestLedger uint32 `json:"latest_indexed_ledger"` -} - -func Root(config RootResponse) func(http.ResponseWriter, *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/hal+json; charset=utf-8") - encoder := json.NewEncoder(w) - encoder.SetIndent("", " ") - err := encoder.Encode(config) - if err != nil { - log.Error(err) - sendErrorResponse(r.Context(), w, supportProblem.ServerError) - } - } -} diff --git a/exp/lighthorizon/actions/static/api_docs.yml b/exp/lighthorizon/actions/static/api_docs.yml deleted file mode 100644 index 281cf2b605..0000000000 --- a/exp/lighthorizon/actions/static/api_docs.yml +++ /dev/null @@ -1,228 +0,0 @@ -openapi: 3.1.0 -info: - title: Horizon Lite API - version: 0.0.1 - description: |- - The Horizon Lite API is a published web service on port 8080. It's considered - extremely experimental and only provides a minimal subset of endpoints. -servers: - - url: http://localhost:8080/ -paths: - /accounts/{account_id}/operations: - get: - operationId: GetOperationsByAccountId - parameters: - - $ref: '#/components/parameters/CursorParam' - - $ref: '#/components/parameters/LimitParam' - - $ref: '#/components/parameters/AccountIDParam' - responses: - '200': - description: OK - headers: {} - content: - application/json: - schema: - $ref: '#/components/schemas/CollectionModel_Operation' - example: - _links: - self: - href: http://localhost:8080/accounts/GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ/operations?cursor=6606617478959105&limit=1&order=asc - next: - href: http://localhost:8080/accounts/GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ/operations?cursor=6606621773926401&limit=1&order=asc - prev: - href: http://localhost:8080/accounts/GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ/operations?cursor=6606621773926401&limit=1&order=desc - _embedded: - records: - - _links: - self: - href: http://localhost:8080/operations/6606621773926401 - id: '6606621773926401' - paging_token: '6606621773926401' - transaction_successful: true - source_account: GBGTCH47BOEEKLPHHMR2GOK6KQFGL3O7Q53FIZTJ7S7YEDWYJ5IUDJDJ - type: manage_sell_offer - type_i: 3 - created_at: '2022-06-17T23:29:42Z' - transaction_hash: 544469b76cd90978345a4734a0ce69a9d0ddb4a6595a7afc503225a77826722a - amount: '0.0000000' - price: '0.0000001' - price_r: - n: 1 - d: 10000000 - buying_asset_type: credit_alphanum4 - buying_asset_code: USDV - buying_asset_issuer: GAXXMQMTDUQ4YEPXJMKFBGN3GETPJNEXEUHFCQJKGJDVI3XQCNBU3OZI - selling_asset_type: credit_alphanum4 - selling_asset_code: EURV - selling_asset_issuer: GAXXMQMTDUQ4YEPXJMKFBGN3GETPJNEXEUHFCQJKGJDVI3XQCNBU3OZI - offer_id: '425531' - summary: Get Operations by Account ID and Paged list - description: Get Operations by Account ID and Paged list - tags: [] - /accounts/{account_id}/transactions: - get: - operationId: GetTransactionsByAccountId - parameters: - - $ref: '#/components/parameters/CursorParam' - - $ref: '#/components/parameters/LimitParam' - - $ref: '#/components/parameters/AccountIDParam' - responses: - '200': - description: OK - headers: {} - content: - application/json: - schema: - $ref: '#/components/schemas/CollectionModel_Tx' - example: - _links: - self: - href: http://localhost:8080/accounts/GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ/transactions?cursor=&limit=0&order= - next: - href: http://localhost:8080/accounts/GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ/transactions?cursor=6606621773930497&limit=0&order= - prev: - href: http://localhost:8080/accounts/GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ/transactions?cursor=6606621773930497&limit=0&order=asc - _embedded: - records: - - memo: xdr.MemoText("psp:1405") - _links: - self: - href: http://localhost:8080/transactions/5fef21d5ef75ecf18d65a160cfab17dca8dbf6dbc4e2fd66a510719ad8dddb09 - id: 5fef21d5ef75ecf18d65a160cfab17dca8dbf6dbc4e2fd66a510719ad8dddb09 - paging_token: '6606621773930497' - successful: false - hash: 5fef21d5ef75ecf18d65a160cfab17dca8dbf6dbc4e2fd66a510719ad8dddb09 - ledger: 1538224 - created_at: '2022-06-17T23:29:42Z' - source_account: GCFJN22UG6IZHXKDVAJWAVEQ3NERGCRCURR2FHARNRBNLYFEQZGML4PW - source_account_sequence: '' - fee_account: '' - fee_charged: '3000' - max_fee: '0' - operation_count: 1 - envelope_xdr: AAAAAgAAAACKlutUN5GT3UOoE2BUkNtJEwoipGOinBFsQtXgpIZMxQAAJxAAE05oAAHUKAAAAAEAAAAAAAAAAAAAAABirQ6AAAAAAQAAAAhwc3A6MTQwNQAAAAEAAAAAAAAAAQAAAADpPdN37FA9KVcJfmMBuD8pPcaT5jqlrMeYEOTP36Zo2AAAAAJBVE1ZUgAAAAAAAAAAAAAAZ8rWY3iaDnWNtfpvLpNaCEbKdDjrd2gQODOuKpmj1vMAAAAAGHAagAAAAAAAAAABpIZMxQAAAEDNJwYToiBR6bzElRL4ORJdXXZYO9cE3-ishQLC_fWGrPGhWrW7_UkPJWvxWdQDJBjVOHuA1Jjc94NSe91hSwEL - result_xdr: AAAAAAAAC7j_____AAAAAQAAAAAAAAAB____-gAAAAA= - result_meta_xdr: '' - fee_meta_xdr: '' - memo_type: MemoTypeMemoText - signatures: - - pIZMxQAAAEDNJwYToiBR6bzElRL4ORJdXXZYO9cE3-ishQLC_fWGrPGhWrW7_UkPJWvxWdQDJBjVOHuA1Jjc94NSe91hSwEL - summary: Get Transactions by Account ID and Paged list - description: Get Transactions by Account ID and Paged list - tags: [] -components: - parameters: - CursorParam: - name: cursor - in: query - required: false - schema: - type: integer - example: 6606617478959105 - description: The packed order id consisting of Ledger Num, TX Order Num, Operation Order Num - LimitParam: - in: query - name: limit - required: false - schema: - type: integer - default: 10 - description: The numbers of items to return - AccountIDParam: - name: account_id - in: path - required: true - description: The strkey encoded Account ID - schema: - type: string - example: GDMQQNJM4UL7QIA66P7R2PZHMQINWZBM77BEBMHLFXD5JEUAHGJ7R4JZ - TransactionIDParam: - name: tx_id - in: path - required: true - description: The Transaction hash, it's id. - schema: - type: string - example: a221f4743450736cba4a78940f22b01e1f64568eec8cb04c2ae37874d86cee3d - schemas: - CollectionModelItem: - type: object - properties: - _embedded: - type: object - properties: - records: - type: array - items: - "$ref": "#/components/schemas/Item" - _links: - "$ref": "#/components/schemas/Links" - Item: - type: object - properties: - id: - type: string - _links: - "$ref": "#/components/schemas/Links" - CollectionModel_Tx: - type: object - allOf: - - $ref: "#/components/schemas/CollectionModelItem" - properties: - _embedded: - type: object - properties: - records: - type: array - items: - $ref: "#/components/schemas/EntityModel_Tx" - EntityModel_Tx: - type: object - allOf: - - $ref: "#/components/schemas/Tx" - - $ref: "#/components/schemas/Links" - Tx: - type: object - properties: - id: - type: string - hash: - type: string - ledger: - type: integer - CollectionModel_Operation: - type: object - allOf: - - $ref: "#/components/schemas/CollectionModelItem" - properties: - _embedded: - type: object - properties: - records: - type: array - items: - $ref: "#/components/schemas/EntityModel_Operation" - EntityModel_Operation: - type: object - allOf: - - $ref: "#/components/schemas/Operation" - - $ref: "#/components/schemas/Links" - Operation: - type: object - properties: - id: - type: string - type: - type: string - source_account: - type: string - Links: - type: object - additionalProperties: - "$ref": "#/components/schemas/Link" - Link: - type: object - properties: - href: - type: string -tags: [] diff --git a/exp/lighthorizon/adapters/account_merge.go b/exp/lighthorizon/adapters/account_merge.go deleted file mode 100644 index 1fa6934638..0000000000 --- a/exp/lighthorizon/adapters/account_merge.go +++ /dev/null @@ -1,21 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateAccountMergeOperation(op *common.Operation, baseOp operations.Base) (operations.AccountMerge, error) { - destination := op.Get().Body.MustDestination() - - return operations.AccountMerge{ - Base: baseOp, - Account: op.SourceAccount().Address(), - Into: destination.Address(), - // TODO: - AccountMuxed: "", - AccountMuxedID: 0, - IntoMuxed: "", - IntoMuxedID: 0, - }, nil -} diff --git a/exp/lighthorizon/adapters/allow_trust.go b/exp/lighthorizon/adapters/allow_trust.go deleted file mode 100644 index 2e3fea2188..0000000000 --- a/exp/lighthorizon/adapters/allow_trust.go +++ /dev/null @@ -1,43 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" -) - -func populateAllowTrustOperation(op *common.Operation, baseOp operations.Base) (operations.AllowTrust, error) { - allowTrust := op.Get().Body.MustAllowTrustOp() - - var ( - assetType string - code string - issuer string - ) - - err := allowTrust.Asset.ToAsset(op.SourceAccount()).Extract(&assetType, &code, &issuer) - if err != nil { - return operations.AllowTrust{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - flags := xdr.TrustLineFlags(allowTrust.Authorize) - - return operations.AllowTrust{ - Base: baseOp, - Asset: base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - }, - - Trustee: op.SourceAccount().Address(), - Trustor: allowTrust.Trustor.Address(), - Authorize: flags.IsAuthorized(), - AuthorizeToMaintainLiabilities: flags.IsAuthorizedToMaintainLiabilitiesFlag(), - // TODO: - TrusteeMuxed: "", - TrusteeMuxedID: 0, - }, nil -} diff --git a/exp/lighthorizon/adapters/begin_sponsoring_future_reserves.go b/exp/lighthorizon/adapters/begin_sponsoring_future_reserves.go deleted file mode 100644 index a5fe86a3ce..0000000000 --- a/exp/lighthorizon/adapters/begin_sponsoring_future_reserves.go +++ /dev/null @@ -1,15 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateBeginSponsoringFutureReservesOperation(op *common.Operation, baseOp operations.Base) (operations.BeginSponsoringFutureReserves, error) { - beginSponsoringFutureReserves := op.Get().Body.MustBeginSponsoringFutureReservesOp() - - return operations.BeginSponsoringFutureReserves{ - Base: baseOp, - SponsoredID: beginSponsoringFutureReserves.SponsoredId.Address(), - }, nil -} diff --git a/exp/lighthorizon/adapters/bump_sequence.go b/exp/lighthorizon/adapters/bump_sequence.go deleted file mode 100644 index 53fe0125a2..0000000000 --- a/exp/lighthorizon/adapters/bump_sequence.go +++ /dev/null @@ -1,17 +0,0 @@ -package adapters - -import ( - "strconv" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateBumpSequenceOperation(op *common.Operation, baseOp operations.Base) (operations.BumpSequence, error) { - bumpSequence := op.Get().Body.MustBumpSequenceOp() - - return operations.BumpSequence{ - Base: baseOp, - BumpTo: strconv.FormatInt(int64(bumpSequence.BumpTo), 10), - }, nil -} diff --git a/exp/lighthorizon/adapters/change_trust.go b/exp/lighthorizon/adapters/change_trust.go deleted file mode 100644 index e06dbcfb39..0000000000 --- a/exp/lighthorizon/adapters/change_trust.go +++ /dev/null @@ -1,63 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" -) - -func populateChangeTrustOperation(op *common.Operation, baseOp operations.Base) (operations.ChangeTrust, error) { - changeTrust := op.Get().Body.MustChangeTrustOp() - - var ( - assetType string - code string - issuer string - - liquidityPoolID string - ) - - switch changeTrust.Line.Type { - case xdr.AssetTypeAssetTypeCreditAlphanum4, xdr.AssetTypeAssetTypeCreditAlphanum12: - err := changeTrust.Line.ToAsset().Extract(&assetType, &code, &issuer) - if err != nil { - return operations.ChangeTrust{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - case xdr.AssetTypeAssetTypePoolShare: - assetType = "liquidity_pool_shares" - - if changeTrust.Line.LiquidityPool.Type != xdr.LiquidityPoolTypeLiquidityPoolConstantProduct { - return operations.ChangeTrust{}, errors.Errorf("unkown liquidity pool type %d", changeTrust.Line.LiquidityPool.Type) - } - - cp := changeTrust.Line.LiquidityPool.ConstantProduct - poolID, err := xdr.NewPoolId(cp.AssetA, cp.AssetB, cp.Fee) - if err != nil { - return operations.ChangeTrust{}, errors.Wrap(err, "error generating pool id") - } - liquidityPoolID = xdr.Hash(poolID).HexString() - default: - return operations.ChangeTrust{}, errors.Errorf("unknown asset type %d", changeTrust.Line.Type) - } - - return operations.ChangeTrust{ - Base: baseOp, - LiquidityPoolOrAsset: base.LiquidityPoolOrAsset{ - Asset: base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - }, - LiquidityPoolID: liquidityPoolID, - }, - Limit: amount.String(changeTrust.Limit), - Trustee: issuer, - Trustor: op.SourceAccount().Address(), - // TODO: - TrustorMuxed: "", - TrustorMuxedID: 0, - }, nil -} diff --git a/exp/lighthorizon/adapters/claim_claimable_balance.go b/exp/lighthorizon/adapters/claim_claimable_balance.go deleted file mode 100644 index 7dffe49d13..0000000000 --- a/exp/lighthorizon/adapters/claim_claimable_balance.go +++ /dev/null @@ -1,26 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" -) - -func populateClaimClaimableBalanceOperation(op *common.Operation, baseOp operations.Base) (operations.ClaimClaimableBalance, error) { - claimClaimableBalance := op.Get().Body.MustClaimClaimableBalanceOp() - - balanceID, err := xdr.MarshalHex(claimClaimableBalance.BalanceId) - if err != nil { - return operations.ClaimClaimableBalance{}, errors.New("invalid balanceId") - } - - return operations.ClaimClaimableBalance{ - Base: baseOp, - BalanceID: balanceID, - Claimant: op.SourceAccount().Address(), - // TODO - ClaimantMuxed: "", - ClaimantMuxedID: 0, - }, nil -} diff --git a/exp/lighthorizon/adapters/clawback.go b/exp/lighthorizon/adapters/clawback.go deleted file mode 100644 index 32f6ed7401..0000000000 --- a/exp/lighthorizon/adapters/clawback.go +++ /dev/null @@ -1,37 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populateClawbackOperation(op *common.Operation, baseOp operations.Base) (operations.Clawback, error) { - clawback := op.Get().Body.MustClawbackOp() - - var ( - assetType string - code string - issuer string - ) - err := clawback.Asset.Extract(&assetType, &code, &issuer) - if err != nil { - return operations.Clawback{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - return operations.Clawback{ - Base: baseOp, - Asset: base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - }, - Amount: amount.String(clawback.Amount), - From: clawback.From.Address(), - // TODO: - FromMuxed: "", - FromMuxedID: 0, - }, nil -} diff --git a/exp/lighthorizon/adapters/clawback_claimable_balance.go b/exp/lighthorizon/adapters/clawback_claimable_balance.go deleted file mode 100644 index a24d4828b0..0000000000 --- a/exp/lighthorizon/adapters/clawback_claimable_balance.go +++ /dev/null @@ -1,22 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" -) - -func populateClawbackClaimableBalanceOperation(op *common.Operation, baseOp operations.Base) (operations.ClawbackClaimableBalance, error) { - clawbackClaimableBalance := op.Get().Body.MustClawbackClaimableBalanceOp() - - balanceID, err := xdr.MarshalHex(clawbackClaimableBalance.BalanceId) - if err != nil { - return operations.ClawbackClaimableBalance{}, errors.Wrap(err, "invalid balanceId") - } - - return operations.ClawbackClaimableBalance{ - Base: baseOp, - BalanceID: balanceID, - }, nil -} diff --git a/exp/lighthorizon/adapters/create_account.go b/exp/lighthorizon/adapters/create_account.go deleted file mode 100644 index d9a7c678a1..0000000000 --- a/exp/lighthorizon/adapters/create_account.go +++ /dev/null @@ -1,18 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateCreateAccountOperation(op *common.Operation, baseOp operations.Base) (operations.CreateAccount, error) { - createAccount := op.Get().Body.MustCreateAccountOp() - - return operations.CreateAccount{ - Base: baseOp, - StartingBalance: amount.String(createAccount.StartingBalance), - Funder: op.SourceAccount().Address(), - Account: createAccount.Destination.Address(), - }, nil -} diff --git a/exp/lighthorizon/adapters/create_claimable_balance.go b/exp/lighthorizon/adapters/create_claimable_balance.go deleted file mode 100644 index 472e43b30c..0000000000 --- a/exp/lighthorizon/adapters/create_claimable_balance.go +++ /dev/null @@ -1,27 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateCreateClaimableBalanceOperation(op *common.Operation, baseOp operations.Base) (operations.CreateClaimableBalance, error) { - createClaimableBalance := op.Get().Body.MustCreateClaimableBalanceOp() - - claimants := make([]horizon.Claimant, len(createClaimableBalance.Claimants)) - for i, claimant := range createClaimableBalance.Claimants { - claimants[i] = horizon.Claimant{ - Destination: claimant.MustV0().Destination.Address(), - Predicate: claimant.MustV0().Predicate, - } - } - - return operations.CreateClaimableBalance{ - Base: baseOp, - Asset: createClaimableBalance.Asset.StringCanonical(), - Amount: amount.String(createClaimableBalance.Amount), - Claimants: claimants, - }, nil -} diff --git a/exp/lighthorizon/adapters/create_passive_sell_offer.go b/exp/lighthorizon/adapters/create_passive_sell_offer.go deleted file mode 100644 index 89b2b29e97..0000000000 --- a/exp/lighthorizon/adapters/create_passive_sell_offer.go +++ /dev/null @@ -1,51 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populateCreatePassiveSellOfferOperation(op *common.Operation, baseOp operations.Base) (operations.CreatePassiveSellOffer, error) { - createPassiveSellOffer := op.Get().Body.MustCreatePassiveSellOfferOp() - - var ( - buyingAssetType string - buyingCode string - buyingIssuer string - ) - err := createPassiveSellOffer.Buying.Extract(&buyingAssetType, &buyingCode, &buyingIssuer) - if err != nil { - return operations.CreatePassiveSellOffer{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - var ( - sellingAssetType string - sellingCode string - sellingIssuer string - ) - err = createPassiveSellOffer.Selling.Extract(&sellingAssetType, &sellingCode, &sellingIssuer) - if err != nil { - return operations.CreatePassiveSellOffer{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - return operations.CreatePassiveSellOffer{ - Offer: operations.Offer{ - Base: baseOp, - Amount: amount.String(createPassiveSellOffer.Amount), - Price: createPassiveSellOffer.Price.String(), - PriceR: base.Price{ - N: int32(createPassiveSellOffer.Price.N), - D: int32(createPassiveSellOffer.Price.D), - }, - BuyingAssetType: buyingAssetType, - BuyingAssetCode: buyingCode, - BuyingAssetIssuer: buyingIssuer, - SellingAssetType: sellingAssetType, - SellingAssetCode: sellingCode, - SellingAssetIssuer: sellingIssuer, - }, - }, nil -} diff --git a/exp/lighthorizon/adapters/end_sponsoring_future_reserves.go b/exp/lighthorizon/adapters/end_sponsoring_future_reserves.go deleted file mode 100644 index b6ca7a1742..0000000000 --- a/exp/lighthorizon/adapters/end_sponsoring_future_reserves.go +++ /dev/null @@ -1,38 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateEndSponsoringFutureReservesOperation(op *common.Operation, baseOp operations.Base) (operations.EndSponsoringFutureReserves, error) { - return operations.EndSponsoringFutureReserves{ - Base: baseOp, - BeginSponsor: findInitatingSandwichSponsor(op), - // TODO - BeginSponsorMuxed: "", - BeginSponsorMuxedID: 0, - }, nil -} - -func findInitatingSandwichSponsor(op *common.Operation) string { - if !op.TransactionResult.Successful() { - // Failed transactions may not have a compliant sandwich structure - // we can rely on (e.g. invalid nesting or a being operation with the wrong sponsoree ID) - // and thus we bail out since we could return incorrect information. - return "" - } - sponsoree := op.SourceAccount() - operations := op.TransactionEnvelope.Operations() - for i := int(op.OpIndex) - 1; i >= 0; i-- { - if beginOp, ok := operations[i].Body.GetBeginSponsoringFutureReservesOp(); ok && - beginOp.SponsoredId.Address() == sponsoree.Address() { - if operations[i].SourceAccount != nil { - return operations[i].SourceAccount.Address() - } else { - return op.TransactionEnvelope.SourceAccount().ToAccountId().Address() - } - } - } - return "" -} diff --git a/exp/lighthorizon/adapters/inflation.go b/exp/lighthorizon/adapters/inflation.go deleted file mode 100644 index 57c927263d..0000000000 --- a/exp/lighthorizon/adapters/inflation.go +++ /dev/null @@ -1,12 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateInflationOperation(op *common.Operation, baseOp operations.Base) (operations.Inflation, error) { - return operations.Inflation{ - Base: baseOp, - }, nil -} diff --git a/exp/lighthorizon/adapters/liquidity_pool_deposit.go b/exp/lighthorizon/adapters/liquidity_pool_deposit.go deleted file mode 100644 index f0b4384009..0000000000 --- a/exp/lighthorizon/adapters/liquidity_pool_deposit.go +++ /dev/null @@ -1,33 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/xdr" -) - -func populateLiquidityPoolDepositOperation(op *common.Operation, baseOp operations.Base) (operations.LiquidityPoolDeposit, error) { - liquidityPoolDeposit := op.Get().Body.MustLiquidityPoolDepositOp() - - return operations.LiquidityPoolDeposit{ - Base: baseOp, - // TODO: some fields missing because derived from meta - LiquidityPoolID: xdr.Hash(liquidityPoolDeposit.LiquidityPoolId).HexString(), - ReservesMax: []base.AssetAmount{ - {Amount: amount.String(liquidityPoolDeposit.MaxAmountA)}, - {Amount: amount.String(liquidityPoolDeposit.MaxAmountB)}, - }, - MinPrice: liquidityPoolDeposit.MinPrice.String(), - MinPriceR: base.Price{ - N: int32(liquidityPoolDeposit.MinPrice.N), - D: int32(liquidityPoolDeposit.MinPrice.D), - }, - MaxPrice: liquidityPoolDeposit.MaxPrice.String(), - MaxPriceR: base.Price{ - N: int32(liquidityPoolDeposit.MaxPrice.N), - D: int32(liquidityPoolDeposit.MaxPrice.D), - }, - }, nil -} diff --git a/exp/lighthorizon/adapters/liquidity_pool_withdraw.go b/exp/lighthorizon/adapters/liquidity_pool_withdraw.go deleted file mode 100644 index c618baf2de..0000000000 --- a/exp/lighthorizon/adapters/liquidity_pool_withdraw.go +++ /dev/null @@ -1,24 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/xdr" -) - -func populateLiquidityPoolWithdrawOperation(op *common.Operation, baseOp operations.Base) (operations.LiquidityPoolWithdraw, error) { - liquidityPoolWithdraw := op.Get().Body.MustLiquidityPoolWithdrawOp() - - return operations.LiquidityPoolWithdraw{ - Base: baseOp, - // TODO: some fields missing because derived from meta - LiquidityPoolID: xdr.Hash(liquidityPoolWithdraw.LiquidityPoolId).HexString(), - ReservesMin: []base.AssetAmount{ - {Amount: amount.String(liquidityPoolWithdraw.MinAmountA)}, - {Amount: amount.String(liquidityPoolWithdraw.MinAmountB)}, - }, - Shares: amount.String(liquidityPoolWithdraw.Amount), - }, nil -} diff --git a/exp/lighthorizon/adapters/manage_buy_offer.go b/exp/lighthorizon/adapters/manage_buy_offer.go deleted file mode 100644 index ccdd66bc69..0000000000 --- a/exp/lighthorizon/adapters/manage_buy_offer.go +++ /dev/null @@ -1,52 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populateManageBuyOfferOperation(op *common.Operation, baseOp operations.Base) (operations.ManageBuyOffer, error) { - manageBuyOffer := op.Get().Body.MustManageBuyOfferOp() - - var ( - buyingAssetType string - buyingCode string - buyingIssuer string - ) - err := manageBuyOffer.Buying.Extract(&buyingAssetType, &buyingCode, &buyingIssuer) - if err != nil { - return operations.ManageBuyOffer{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - var ( - sellingAssetType string - sellingCode string - sellingIssuer string - ) - err = manageBuyOffer.Selling.Extract(&sellingAssetType, &sellingCode, &sellingIssuer) - if err != nil { - return operations.ManageBuyOffer{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - return operations.ManageBuyOffer{ - Offer: operations.Offer{ - Base: baseOp, - Amount: amount.String(manageBuyOffer.BuyAmount), - Price: manageBuyOffer.Price.String(), - PriceR: base.Price{ - N: int32(manageBuyOffer.Price.N), - D: int32(manageBuyOffer.Price.D), - }, - BuyingAssetType: buyingAssetType, - BuyingAssetCode: buyingCode, - BuyingAssetIssuer: buyingIssuer, - SellingAssetType: sellingAssetType, - SellingAssetCode: sellingCode, - SellingAssetIssuer: sellingIssuer, - }, - OfferID: int64(manageBuyOffer.OfferId), - }, nil -} diff --git a/exp/lighthorizon/adapters/manage_data.go b/exp/lighthorizon/adapters/manage_data.go deleted file mode 100644 index dd66ed2ae4..0000000000 --- a/exp/lighthorizon/adapters/manage_data.go +++ /dev/null @@ -1,23 +0,0 @@ -package adapters - -import ( - "encoding/base64" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" -) - -func populateManageDataOperation(op *common.Operation, baseOp operations.Base) (operations.ManageData, error) { - manageData := op.Get().Body.MustManageDataOp() - - dataValue := "" - if manageData.DataValue != nil { - dataValue = base64.StdEncoding.EncodeToString(*manageData.DataValue) - } - - return operations.ManageData{ - Base: baseOp, - Name: string(manageData.DataName), - Value: dataValue, - }, nil -} diff --git a/exp/lighthorizon/adapters/manage_sell_offer.go b/exp/lighthorizon/adapters/manage_sell_offer.go deleted file mode 100644 index 56893cc1ab..0000000000 --- a/exp/lighthorizon/adapters/manage_sell_offer.go +++ /dev/null @@ -1,52 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populateManageSellOfferOperation(op *common.Operation, baseOp operations.Base) (operations.ManageSellOffer, error) { - manageSellOffer := op.Get().Body.MustManageSellOfferOp() - - var ( - buyingAssetType string - buyingCode string - buyingIssuer string - ) - err := manageSellOffer.Buying.Extract(&buyingAssetType, &buyingCode, &buyingIssuer) - if err != nil { - return operations.ManageSellOffer{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - var ( - sellingAssetType string - sellingCode string - sellingIssuer string - ) - err = manageSellOffer.Selling.Extract(&sellingAssetType, &sellingCode, &sellingIssuer) - if err != nil { - return operations.ManageSellOffer{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - return operations.ManageSellOffer{ - Offer: operations.Offer{ - Base: baseOp, - Amount: amount.String(manageSellOffer.Amount), - Price: manageSellOffer.Price.String(), - PriceR: base.Price{ - N: int32(manageSellOffer.Price.N), - D: int32(manageSellOffer.Price.D), - }, - BuyingAssetType: buyingAssetType, - BuyingAssetCode: buyingCode, - BuyingAssetIssuer: buyingIssuer, - SellingAssetType: sellingAssetType, - SellingAssetCode: sellingCode, - SellingAssetIssuer: sellingIssuer, - }, - OfferID: int64(manageSellOffer.OfferId), - }, nil -} diff --git a/exp/lighthorizon/adapters/operation.go b/exp/lighthorizon/adapters/operation.go deleted file mode 100644 index a2448c8c58..0000000000 --- a/exp/lighthorizon/adapters/operation.go +++ /dev/null @@ -1,93 +0,0 @@ -package adapters - -import ( - "fmt" - "net/http" - "strconv" - "time" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/render/hal" - "github.com/stellar/go/xdr" -) - -func PopulateOperation(r *http.Request, op *common.Operation) (operations.Operation, error) { - hash, err := op.TransactionHash() - if err != nil { - return nil, err - } - - toid := strconv.FormatInt(op.TOID(), 10) - baseOp := operations.Base{ - ID: toid, - PT: toid, - TransactionSuccessful: op.TransactionResult.Successful(), - SourceAccount: op.SourceAccount().Address(), - LedgerCloseTime: time.Unix(int64(op.LedgerHeader.ScpValue.CloseTime), 0).UTC(), - TransactionHash: hash, - Type: operations.TypeNames[op.Get().Body.Type], - TypeI: int32(op.Get().Body.Type), - } - - lb := hal.LinkBuilder{Base: r.URL} - self := fmt.Sprintf("/operations/%s", toid) - baseOp.Links.Self = lb.Link(self) - baseOp.Links.Succeeds = lb.Linkf("/effects?order=desc&cursor=%s", baseOp.PT) - baseOp.Links.Precedes = lb.Linkf("/effects?order=asc&cursor=%s", baseOp.PT) - baseOp.Links.Transaction = lb.Linkf("/transactions/%s", hash) - baseOp.Links.Effects = lb.Link(self, "effects") - - switch op.Get().Body.Type { - case xdr.OperationTypeCreateAccount: - return populateCreateAccountOperation(op, baseOp) - case xdr.OperationTypePayment: - return populatePaymentOperation(op, baseOp) - case xdr.OperationTypePathPaymentStrictReceive: - return populatePathPaymentStrictReceiveOperation(op, baseOp) - case xdr.OperationTypePathPaymentStrictSend: - return populatePathPaymentStrictSendOperation(op, baseOp) - case xdr.OperationTypeManageBuyOffer: - return populateManageBuyOfferOperation(op, baseOp) - case xdr.OperationTypeManageSellOffer: - return populateManageSellOfferOperation(op, baseOp) - case xdr.OperationTypeCreatePassiveSellOffer: - return populateCreatePassiveSellOfferOperation(op, baseOp) - case xdr.OperationTypeSetOptions: - return populateSetOptionsOperation(op, baseOp) - case xdr.OperationTypeChangeTrust: - return populateChangeTrustOperation(op, baseOp) - case xdr.OperationTypeAllowTrust: - return populateAllowTrustOperation(op, baseOp) - case xdr.OperationTypeAccountMerge: - return populateAccountMergeOperation(op, baseOp) - case xdr.OperationTypeInflation: - return populateInflationOperation(op, baseOp) - case xdr.OperationTypeManageData: - return populateManageDataOperation(op, baseOp) - case xdr.OperationTypeBumpSequence: - return populateBumpSequenceOperation(op, baseOp) - case xdr.OperationTypeCreateClaimableBalance: - return populateCreateClaimableBalanceOperation(op, baseOp) - case xdr.OperationTypeClaimClaimableBalance: - return populateClaimClaimableBalanceOperation(op, baseOp) - case xdr.OperationTypeBeginSponsoringFutureReserves: - return populateBeginSponsoringFutureReservesOperation(op, baseOp) - case xdr.OperationTypeEndSponsoringFutureReserves: - return populateEndSponsoringFutureReservesOperation(op, baseOp) - case xdr.OperationTypeRevokeSponsorship: - return populateRevokeSponsorshipOperation(op, baseOp) - case xdr.OperationTypeClawback: - return populateClawbackOperation(op, baseOp) - case xdr.OperationTypeClawbackClaimableBalance: - return populateClawbackClaimableBalanceOperation(op, baseOp) - case xdr.OperationTypeSetTrustLineFlags: - return populateSetTrustLineFlagsOperation(op, baseOp) - case xdr.OperationTypeLiquidityPoolDeposit: - return populateLiquidityPoolDepositOperation(op, baseOp) - case xdr.OperationTypeLiquidityPoolWithdraw: - return populateLiquidityPoolWithdrawOperation(op, baseOp) - default: - return nil, fmt.Errorf("unknown operation type: %s", op.Get().Body.Type) - } -} diff --git a/exp/lighthorizon/adapters/path_payment_strict_receive.go b/exp/lighthorizon/adapters/path_payment_strict_receive.go deleted file mode 100644 index eeaabad969..0000000000 --- a/exp/lighthorizon/adapters/path_payment_strict_receive.go +++ /dev/null @@ -1,78 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populatePathPaymentStrictReceiveOperation(op *common.Operation, baseOp operations.Base) (operations.PathPayment, error) { - payment := op.Get().Body.MustPathPaymentStrictReceiveOp() - - var ( - sendAssetType string - sendCode string - sendIssuer string - ) - err := payment.SendAsset.Extract(&sendAssetType, &sendCode, &sendIssuer) - if err != nil { - return operations.PathPayment{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - var ( - destAssetType string - destCode string - destIssuer string - ) - err = payment.DestAsset.Extract(&destAssetType, &destCode, &destIssuer) - if err != nil { - return operations.PathPayment{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - sourceAmount := amount.String(0) - if op.TransactionResult.Successful() { - result := op.OperationResult().MustPathPaymentStrictReceiveResult() - sourceAmount = amount.String(result.SendAmount()) - } - - var path = make([]base.Asset, len(payment.Path)) - for i := range payment.Path { - var ( - assetType string - code string - issuer string - ) - err = payment.Path[i].Extract(&assetType, &code, &issuer) - if err != nil { - return operations.PathPayment{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - path[i] = base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - } - } - - return operations.PathPayment{ - Payment: operations.Payment{ - Base: baseOp, - From: op.SourceAccount().Address(), - To: payment.Destination.Address(), - Asset: base.Asset{ - Type: destAssetType, - Code: destCode, - Issuer: destIssuer, - }, - Amount: amount.String(payment.DestAmount), - }, - Path: path, - SourceAmount: sourceAmount, - SourceMax: amount.String(payment.SendMax), - SourceAssetType: sendAssetType, - SourceAssetCode: sendCode, - SourceAssetIssuer: sendIssuer, - }, nil -} diff --git a/exp/lighthorizon/adapters/path_payment_strict_send.go b/exp/lighthorizon/adapters/path_payment_strict_send.go deleted file mode 100644 index 0068db30b5..0000000000 --- a/exp/lighthorizon/adapters/path_payment_strict_send.go +++ /dev/null @@ -1,78 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populatePathPaymentStrictSendOperation(op *common.Operation, baseOp operations.Base) (operations.PathPaymentStrictSend, error) { - payment := op.Get().Body.MustPathPaymentStrictSendOp() - - var ( - sendAssetType string - sendCode string - sendIssuer string - ) - err := payment.SendAsset.Extract(&sendAssetType, &sendCode, &sendIssuer) - if err != nil { - return operations.PathPaymentStrictSend{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - var ( - destAssetType string - destCode string - destIssuer string - ) - err = payment.DestAsset.Extract(&destAssetType, &destCode, &destIssuer) - if err != nil { - return operations.PathPaymentStrictSend{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - destAmount := amount.String(0) - if op.TransactionResult.Successful() { - result := op.OperationResult().MustPathPaymentStrictSendResult() - destAmount = amount.String(result.DestAmount()) - } - - var path = make([]base.Asset, len(payment.Path)) - for i := range payment.Path { - var ( - assetType string - code string - issuer string - ) - err = payment.Path[i].Extract(&assetType, &code, &issuer) - if err != nil { - return operations.PathPaymentStrictSend{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - path[i] = base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - } - } - - return operations.PathPaymentStrictSend{ - Payment: operations.Payment{ - Base: baseOp, - From: op.SourceAccount().Address(), - To: payment.Destination.Address(), - Asset: base.Asset{ - Type: destAssetType, - Code: destCode, - Issuer: destIssuer, - }, - Amount: destAmount, - }, - Path: path, - SourceAmount: amount.String(payment.SendAmount), - DestinationMin: amount.String(payment.DestMin), - SourceAssetType: sendAssetType, - SourceAssetCode: sendCode, - SourceAssetIssuer: sendIssuer, - }, nil -} diff --git a/exp/lighthorizon/adapters/payment.go b/exp/lighthorizon/adapters/payment.go deleted file mode 100644 index 97af5f6120..0000000000 --- a/exp/lighthorizon/adapters/payment.go +++ /dev/null @@ -1,35 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/amount" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" -) - -func populatePaymentOperation(op *common.Operation, baseOp operations.Base) (operations.Payment, error) { - payment := op.Get().Body.MustPaymentOp() - - var ( - assetType string - code string - issuer string - ) - err := payment.Asset.Extract(&assetType, &code, &issuer) - if err != nil { - return operations.Payment{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - return operations.Payment{ - Base: baseOp, - To: payment.Destination.Address(), - From: op.SourceAccount().Address(), - Asset: base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - }, - Amount: amount.StringFromInt64(int64(payment.Amount)), - }, nil -} diff --git a/exp/lighthorizon/adapters/revoke_sponsorship.go b/exp/lighthorizon/adapters/revoke_sponsorship.go deleted file mode 100644 index cb19decc5c..0000000000 --- a/exp/lighthorizon/adapters/revoke_sponsorship.go +++ /dev/null @@ -1,66 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" -) - -func populateRevokeSponsorshipOperation(op *common.Operation, baseOp operations.Base) (operations.RevokeSponsorship, error) { - revokeSponsorship := op.Get().Body.MustRevokeSponsorshipOp() - - switch revokeSponsorship.Type { - case xdr.RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: - ret := operations.RevokeSponsorship{ - Base: baseOp, - } - - ledgerKey := revokeSponsorship.LedgerKey - - switch ledgerKey.Type { - case xdr.LedgerEntryTypeAccount: - accountID := ledgerKey.Account.AccountId.Address() - ret.AccountID = &accountID - case xdr.LedgerEntryTypeClaimableBalance: - marshalHex, err := xdr.MarshalHex(ledgerKey.ClaimableBalance.BalanceId) - if err != nil { - return operations.RevokeSponsorship{}, err - } - ret.ClaimableBalanceID = &marshalHex - case xdr.LedgerEntryTypeData: - accountID := ledgerKey.Data.AccountId.Address() - dataName := string(ledgerKey.Data.DataName) - ret.DataAccountID = &accountID - ret.DataName = &dataName - case xdr.LedgerEntryTypeOffer: - offerID := int64(ledgerKey.Offer.OfferId) - ret.OfferID = &offerID - case xdr.LedgerEntryTypeTrustline: - trustlineAccountID := ledgerKey.TrustLine.AccountId.Address() - ret.TrustlineAccountID = &trustlineAccountID - if ledgerKey.TrustLine.Asset.Type == xdr.AssetTypeAssetTypePoolShare { - trustlineLiquidityPoolID := xdr.Hash(*ledgerKey.TrustLine.Asset.LiquidityPoolId).HexString() - ret.TrustlineLiquidityPoolID = &trustlineLiquidityPoolID - } else { - trustlineAsset := ledgerKey.TrustLine.Asset.ToAsset().StringCanonical() - ret.TrustlineAsset = &trustlineAsset - } - default: - return operations.RevokeSponsorship{}, errors.Errorf("invalid ledger key type: %d", ledgerKey.Type) - } - - return ret, nil - case xdr.RevokeSponsorshipTypeRevokeSponsorshipSigner: - signerAccountID := revokeSponsorship.Signer.AccountId.Address() - signerKey := revokeSponsorship.Signer.SignerKey.Address() - - return operations.RevokeSponsorship{ - Base: baseOp, - SignerAccountID: &signerAccountID, - SignerKey: &signerKey, - }, nil - } - - return operations.RevokeSponsorship{}, errors.Errorf("invalid revoke type: %d", revokeSponsorship.Type) -} diff --git a/exp/lighthorizon/adapters/set_options.go b/exp/lighthorizon/adapters/set_options.go deleted file mode 100644 index cf2cdeb20f..0000000000 --- a/exp/lighthorizon/adapters/set_options.go +++ /dev/null @@ -1,122 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/xdr" -) - -func populateSetOptionsOperation(op *common.Operation, baseOp operations.Base) (operations.SetOptions, error) { - setOptions := op.Get().Body.MustSetOptionsOp() - - homeDomain := "" - if setOptions.HomeDomain != nil { - homeDomain = string(*setOptions.HomeDomain) - } - - inflationDest := "" - if setOptions.InflationDest != nil { - inflationDest = setOptions.InflationDest.Address() - } - - var signerKey string - var signerWeight *int - if setOptions.Signer != nil { - signerKey = setOptions.Signer.Key.Address() - signerWeightInt := int(setOptions.Signer.Weight) - signerWeight = &signerWeightInt - } - - var masterKeyWeight, lowThreshold, medThreshold, highThreshold *int - if setOptions.MasterWeight != nil { - masterKeyWeightInt := int(*setOptions.MasterWeight) - masterKeyWeight = &masterKeyWeightInt - } - if setOptions.LowThreshold != nil { - lowThresholdInt := int(*setOptions.LowThreshold) - lowThreshold = &lowThresholdInt - } - if setOptions.MedThreshold != nil { - medThresholdInt := int(*setOptions.MedThreshold) - medThreshold = &medThresholdInt - } - if setOptions.HighThreshold != nil { - highThresholdInt := int(*setOptions.HighThreshold) - highThreshold = &highThresholdInt - } - - var ( - setFlags []int - setFlagsS []string - - clearFlags []int - clearFlagsS []string - ) - - if setOptions.SetFlags != nil && *setOptions.SetFlags > 0 { - f := xdr.AccountFlags(*setOptions.SetFlags) - - if f.IsAuthRequired() { - setFlags = append(setFlags, int(xdr.AccountFlagsAuthRequiredFlag)) - setFlagsS = append(setFlagsS, "auth_required") - } - - if f.IsAuthRevocable() { - setFlags = append(setFlags, int(xdr.AccountFlagsAuthRevocableFlag)) - setFlagsS = append(setFlagsS, "auth_revocable") - } - - if f.IsAuthImmutable() { - setFlags = append(setFlags, int(xdr.AccountFlagsAuthImmutableFlag)) - setFlagsS = append(setFlagsS, "auth_immutable") - } - - if f.IsAuthClawbackEnabled() { - setFlags = append(setFlags, int(xdr.AccountFlagsAuthClawbackEnabledFlag)) - setFlagsS = append(setFlagsS, "auth_clawback_enabled") - } - } - - if setOptions.ClearFlags != nil && *setOptions.ClearFlags > 0 { - f := xdr.AccountFlags(*setOptions.ClearFlags) - - if f.IsAuthRequired() { - clearFlags = append(clearFlags, int(xdr.AccountFlagsAuthRequiredFlag)) - clearFlagsS = append(clearFlagsS, "auth_required") - } - - if f.IsAuthRevocable() { - clearFlags = append(clearFlags, int(xdr.AccountFlagsAuthRevocableFlag)) - clearFlagsS = append(clearFlagsS, "auth_revocable") - } - - if f.IsAuthImmutable() { - clearFlags = append(clearFlags, int(xdr.AccountFlagsAuthImmutableFlag)) - clearFlagsS = append(clearFlagsS, "auth_immutable") - } - - if f.IsAuthClawbackEnabled() { - clearFlags = append(clearFlags, int(xdr.AccountFlagsAuthClawbackEnabledFlag)) - clearFlagsS = append(clearFlagsS, "auth_clawback_enabled") - } - } - - return operations.SetOptions{ - Base: baseOp, - HomeDomain: homeDomain, - InflationDest: inflationDest, - - MasterKeyWeight: masterKeyWeight, - SignerKey: signerKey, - SignerWeight: signerWeight, - - SetFlags: setFlags, - SetFlagsS: setFlagsS, - ClearFlags: clearFlags, - ClearFlagsS: clearFlagsS, - - LowThreshold: lowThreshold, - MedThreshold: medThreshold, - HighThreshold: highThreshold, - }, nil -} diff --git a/exp/lighthorizon/adapters/set_trust_line_flags.go b/exp/lighthorizon/adapters/set_trust_line_flags.go deleted file mode 100644 index 2969dcb2b5..0000000000 --- a/exp/lighthorizon/adapters/set_trust_line_flags.go +++ /dev/null @@ -1,83 +0,0 @@ -package adapters - -import ( - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/protocols/horizon/base" - "github.com/stellar/go/protocols/horizon/operations" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/xdr" -) - -func populateSetTrustLineFlagsOperation(op *common.Operation, baseOp operations.Base) (operations.SetTrustLineFlags, error) { - setTrustLineFlags := op.Get().Body.MustSetTrustLineFlagsOp() - - var ( - assetType string - code string - issuer string - ) - err := setTrustLineFlags.Asset.Extract(&assetType, &code, &issuer) - if err != nil { - return operations.SetTrustLineFlags{}, errors.Wrap(err, "xdr.Asset.Extract error") - } - - var ( - setFlags []int - setFlagsS []string - - clearFlags []int - clearFlagsS []string - ) - - if setTrustLineFlags.SetFlags > 0 { - f := xdr.TrustLineFlags(setTrustLineFlags.SetFlags) - - if f.IsAuthorized() { - setFlags = append(setFlags, int(xdr.TrustLineFlagsAuthorizedFlag)) - setFlagsS = append(setFlagsS, "authorized") - } - - if f.IsAuthorizedToMaintainLiabilitiesFlag() { - setFlags = append(setFlags, int(xdr.TrustLineFlagsAuthorizedToMaintainLiabilitiesFlag)) - setFlagsS = append(setFlagsS, "authorized_to_maintain_liabilites") - } - - if f.IsClawbackEnabledFlag() { - setFlags = append(setFlags, int(xdr.TrustLineFlagsTrustlineClawbackEnabledFlag)) - setFlagsS = append(setFlagsS, "clawback_enabled") - } - } - - if setTrustLineFlags.ClearFlags > 0 { - f := xdr.TrustLineFlags(setTrustLineFlags.ClearFlags) - - if f.IsAuthorized() { - clearFlags = append(clearFlags, int(xdr.TrustLineFlagsAuthorizedFlag)) - clearFlagsS = append(clearFlagsS, "authorized") - } - - if f.IsAuthorizedToMaintainLiabilitiesFlag() { - clearFlags = append(clearFlags, int(xdr.TrustLineFlagsAuthorizedToMaintainLiabilitiesFlag)) - clearFlagsS = append(clearFlagsS, "authorized_to_maintain_liabilites") - } - - if f.IsClawbackEnabledFlag() { - clearFlags = append(clearFlags, int(xdr.TrustLineFlagsTrustlineClawbackEnabledFlag)) - clearFlagsS = append(clearFlagsS, "clawback_enabled") - } - } - - return operations.SetTrustLineFlags{ - Base: baseOp, - Asset: base.Asset{ - Type: assetType, - Code: code, - Issuer: issuer, - }, - Trustor: setTrustLineFlags.Trustor.Address(), - SetFlags: setFlags, - SetFlagsS: setFlagsS, - ClearFlags: clearFlags, - ClearFlagsS: clearFlagsS, - }, nil -} diff --git a/exp/lighthorizon/adapters/testdata/transactions.json b/exp/lighthorizon/adapters/testdata/transactions.json deleted file mode 100644 index 6128801533..0000000000 --- a/exp/lighthorizon/adapters/testdata/transactions.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "_links": { - "self": { - "href": "https://horizon.stellar.org/accounts/GBFHFINUD6NVGSX33PY25DDRCABN3H2JTDMLUEXAUEJVV22HTXVGLEZD/transactions?cursor=179530990183178241\u0026limit=1\u0026order=desc" - }, - "next": { - "href": "https://horizon.stellar.org/accounts/GBFHFINUD6NVGSX33PY25DDRCABN3H2JTDMLUEXAUEJVV22HTXVGLEZD/transactions?cursor=179530990183174144\u0026limit=1\u0026order=desc" - }, - "prev": { - "href": "https://horizon.stellar.org/accounts/GBFHFINUD6NVGSX33PY25DDRCABN3H2JTDMLUEXAUEJVV22HTXVGLEZD/transactions?cursor=179530990183174144\u0026limit=1\u0026order=asc" - } - }, - "_embedded": { - "records": [ - { - "_links": { - "self": { - "href": "https://horizon.stellar.org/transactions/55d8aa3693489ffc1d70b8ba33b8b5c012ec098f6f104383e3f090048488febd" - }, - "account": { - "href": "https://horizon.stellar.org/accounts/GBFHFINUD6NVGSX33PY25DDRCABN3H2JTDMLUEXAUEJVV22HTXVGLEZD" - }, - "ledger": { - "href": "https://horizon.stellar.org/ledgers/41800316" - }, - "operations": { - "href": "https://horizon.stellar.org/transactions/55d8aa3693489ffc1d70b8ba33b8b5c012ec098f6f104383e3f090048488febd/operations{?cursor,limit,order}", - "templated": true - }, - "effects": { - "href": "https://horizon.stellar.org/transactions/55d8aa3693489ffc1d70b8ba33b8b5c012ec098f6f104383e3f090048488febd/effects{?cursor,limit,order}", - "templated": true - }, - "precedes": { - "href": "https://horizon.stellar.org/transactions?order=asc\u0026cursor=179530990183174144" - }, - "succeeds": { - "href": "https://horizon.stellar.org/transactions?order=desc\u0026cursor=179530990183174144" - }, - "transaction": { - "href": "https://horizon.stellar.org/transactions/55d8aa3693489ffc1d70b8ba33b8b5c012ec098f6f104383e3f090048488febd" - } - }, - "id": "55d8aa3693489ffc1d70b8ba33b8b5c012ec098f6f104383e3f090048488febd", - "paging_token": "179530990183174144", - "successful": true, - "hash": "55d8aa3693489ffc1d70b8ba33b8b5c012ec098f6f104383e3f090048488febd", - "ledger": 41800316, - "created_at": "2022-07-17T13:08:41Z", - "source_account": "GBFHFINUD6NVGSX33PY25DDRCABN3H2JTDMLUEXAUEJVV22HTXVGLEZD", - "source_account_sequence": "172589382434294350", - "fee_account": "GBFHFINUD6NVGSX33PY25DDRCABN3H2JTDMLUEXAUEJVV22HTXVGLEZD", - "fee_charged": "100", - "max_fee": "100000", - "operation_count": 1, - "envelope_xdr": "AAAAAgAAAABKcqG0H5tTSvvb8a6McRAC3Z9JmNi6EuChE1rrR53qZQABhqACZSkhAAAKTgAAAAAAAAAAAAAAAQAAAAEAAAAASnKhtB+bU0r72/GujHEQAt2fSZjYuhLgoRNa60ed6mUAAAANAAAAAXlYTE0AAAAAIjbXcP4NPgFSGXXVz3rEhCtwldaxqddo0+mmMumZBr4AAAACVAvkAAAAAABKcqG0H5tTSvvb8a6McRAC3Z9JmNi6EuChE1rrR53qZQAAAAJEUklGVAAAAAAAAAAAAAAAvSOzPqUOGnDIcJOm7T85qDFRM0wfOVoubgkEPk95DZ0AAAEQvqAGdQAAAAEAAAAAAAAAAAAAAAFHneplAAAAQAVm9muIrK31Z+m2ZvhDYhtuoHcc/n+MO0DOaiQjfW+tsUNVCOw7foHiDRVLBdAHBZT+xxa3F+Ek9wQiKzxtQQM=", - "result_xdr": "AAAAAAAAAGQAAAAAAAAAAQAAAAAAAAANAAAAAAAAAAIAAAABAAAAAPaTW9sBV2ja6yDUtPcpGpUrnVEHaTHC4I065TklIsguAAAAAD1H0goAAAAAAAAAAlQE8wsAAAABeVhMTQAAAAAiNtdw/g0+AVIZddXPesSEK3CV1rGp12jT6aYy6ZkGvgAAAAJUC+QAAAAAAgRnzllf8Sas0MUQlkxROsBgUzEoIN2XrYP9tlH5SINjAAAAAkRSSUZUAAAAAAAAAAAAAAC9I7M+pQ4acMhwk6btPzmoMVEzTB85Wi5uCQQ+T3kNnQAAARN/56NFAAAAAAAAAAJUBPMLAAAAAEpyobQfm1NK+9vxroxxEALdn0mY2LoS4KETWutHneplAAAAAkRSSUZUAAAAAAAAAAAAAAC9I7M+pQ4acMhwk6btPzmoMVEzTB85Wi5uCQQ+T3kNnQAAARN/56NFAAAAAA==", - "result_meta_xdr": "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", - "fee_meta_xdr": "AAAAAgAAAAMCfdJjAAAAAAAAAABKcqG0H5tTSvvb8a6McRAC3Z9JmNi6EuChE1rrR53qZQAAAAAQ2K4DAmUpIQAACk0AAAAKAAAAAQAAAADEccZDcGLJUGqJNC5TihraQE0vQc8dOiVfQyH3xuDhdQAAAAAAAAAJbG9ic3RyLmNvAAAAAQAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAJ90mMAAAAAYtQJSQAAAAAAAAABAn3SfAAAAAAAAAAASnKhtB+bU0r72/GujHEQAt2fSZjYuhLgoRNa60ed6mUAAAAAENitnwJlKSEAAApNAAAACgAAAAEAAAAAxHHGQ3BiyVBqiTQuU4oa2kBNL0HPHTolX0Mh98bg4XUAAAAAAAAACWxvYnN0ci5jbwAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAwAAAAACfdJjAAAAAGLUCUkAAAAA", - "memo_type": "none", - "signatures": [ - "BWb2a4isrfVn6bZm+ENiG26gdxz+f4w7QM5qJCN9b62xQ1UI7Dt+geINFUsF0AcFlP7HFrcX4ST3BCIrPG1BAw==" - ] - } - ] - } -} \ No newline at end of file diff --git a/exp/lighthorizon/adapters/transaction.go b/exp/lighthorizon/adapters/transaction.go deleted file mode 100644 index 6942668c8d..0000000000 --- a/exp/lighthorizon/adapters/transaction.go +++ /dev/null @@ -1,295 +0,0 @@ -package adapters - -import ( - "bytes" - "encoding/base64" - "encoding/hex" - "fmt" - "net/url" - "strconv" - "strings" - "time" - "unicode/utf8" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/network" - protocol "github.com/stellar/go/protocols/horizon" - "github.com/stellar/go/support/render/hal" - "github.com/stellar/go/xdr" - "golang.org/x/exp/constraints" -) - -// PopulateTransaction converts between ingested XDR and RESTful JSON. In -// Horizon Classic, the data goes from Captive Core -> DB -> JSON. In our case, -// there's no DB intermediary, so we need to directly translate. -func PopulateTransaction( - baseUrl *url.URL, - tx *common.Transaction, - encoder *xdr.EncodingBuffer, -) (dest protocol.Transaction, err error) { - txHash, err := tx.TransactionHash() - if err != nil { - return - } - - dest.ID = txHash - dest.Successful = tx.Result.Successful() - dest.Hash = txHash - dest.Ledger = int32(tx.LedgerHeader.LedgerSeq) - dest.LedgerCloseTime = time.Unix(int64(tx.LedgerHeader.ScpValue.CloseTime), 0).UTC() - - source := tx.SourceAccount() - dest.Account = source.ToAccountId().Address() - if _, ok := source.GetMed25519(); ok { - dest.AccountMuxed, err = source.GetAddress() - if err != nil { - return - } - dest.AccountMuxedID, err = source.GetId() - if err != nil { - return - } - } - dest.AccountSequence = tx.Envelope.SeqNum() - - envelopeBase64, err := encoder.MarshalBase64(tx.Envelope) - if err != nil { - return - } - resultBase64, err := encoder.MarshalBase64(&tx.Result.Result) - if err != nil { - return - } - metaBase64, err := encoder.MarshalBase64(tx.UnsafeMeta) - if err != nil { - return - } - feeMetaBase64, err := encoder.MarshalBase64(tx.FeeChanges) - if err != nil { - return - } - - dest.OperationCount = int32(len(tx.Envelope.Operations())) - dest.EnvelopeXdr = envelopeBase64 - dest.ResultXdr = resultBase64 - dest.ResultMetaXdr = metaBase64 - dest.FeeMetaXdr = feeMetaBase64 - dest.MemoType = memoType(*tx.LedgerTransaction) - if m, ok := memo(*tx.LedgerTransaction); ok { - dest.Memo = m - if dest.MemoType == "text" { - var mb string - if mb, err = memoBytes(envelopeBase64); err != nil { - return - } else { - dest.MemoBytes = mb - } - } - } - - dest.Signatures = signatures(tx.Envelope.Signatures()) - - // If we never use this, we'll remove it later. This just defends us against - // nil dereferences. - dest.Preconditions = &protocol.TransactionPreconditions{} - - if tb := tx.Envelope.Preconditions().TimeBounds; tb != nil { - dest.Preconditions.TimeBounds = &protocol.TransactionPreconditionsTimebounds{ - MaxTime: formatTime(tb.MaxTime), - MinTime: formatTime(tb.MinTime), - } - } - - if lb := tx.Envelope.LedgerBounds(); lb != nil { - dest.Preconditions.LedgerBounds = &protocol.TransactionPreconditionsLedgerbounds{ - MinLedger: uint32(lb.MinLedger), - MaxLedger: uint32(lb.MaxLedger), - } - } - - if minSeq := tx.Envelope.MinSeqNum(); minSeq != nil { - dest.Preconditions.MinAccountSequence = fmt.Sprint(*minSeq) - } - - if minSeqAge := tx.Envelope.MinSeqAge(); minSeqAge != nil && *minSeqAge > 0 { - dest.Preconditions.MinAccountSequenceAge = formatTime(*minSeqAge) - } - - if minSeqGap := tx.Envelope.MinSeqLedgerGap(); minSeqGap != nil { - dest.Preconditions.MinAccountSequenceLedgerGap = uint32(*minSeqGap) - } - - if signers := tx.Envelope.ExtraSigners(); len(signers) > 0 { - dest.Preconditions.ExtraSigners = formatSigners(signers) - } - - if tx.Envelope.IsFeeBump() { - innerTx, ok := tx.Envelope.FeeBump.Tx.InnerTx.GetV1() - if !ok { - panic("Failed to parse inner transaction from fee-bump tx.") - } - - var rawInnerHash [32]byte - rawInnerHash, err = network.HashTransaction(innerTx.Tx, tx.NetworkPassphrase) - if err != nil { - return - } - innerHash := hex.EncodeToString(rawInnerHash[:]) - - feeAccountMuxed := tx.Envelope.FeeBumpAccount() - dest.FeeAccount = feeAccountMuxed.ToAccountId().Address() - if _, ok := feeAccountMuxed.GetMed25519(); ok { - dest.FeeAccountMuxed, err = feeAccountMuxed.GetAddress() - if err != nil { - return - } - dest.FeeAccountMuxedID, err = feeAccountMuxed.GetId() - if err != nil { - return - } - } - - dest.MaxFee = tx.Envelope.FeeBumpFee() - dest.FeeBumpTransaction = &protocol.FeeBumpTransaction{ - Hash: txHash, - Signatures: signatures(tx.Envelope.FeeBumpSignatures()), - } - dest.InnerTransaction = &protocol.InnerTransaction{ - Hash: innerHash, - MaxFee: int64(innerTx.Tx.Fee), - Signatures: signatures(tx.Envelope.Signatures()), - } - // TODO: Figure out what this means? Maybe @tamirms knows. - // if transactionHash != row.TransactionHash { - // dest.Signatures = dest.InnerTransaction.Signatures - // } - } else { - dest.FeeAccount = dest.Account - dest.FeeAccountMuxed = dest.AccountMuxed - dest.FeeAccountMuxedID = dest.AccountMuxedID - dest.MaxFee = int64(tx.Envelope.Fee()) - } - dest.FeeCharged = int64(tx.Result.Result.FeeCharged) - - lb := hal.LinkBuilder{Base: baseUrl} - dest.PT = strconv.FormatUint(uint64(tx.TOID()), 10) - dest.Links.Account = lb.Link("/accounts", dest.Account) - dest.Links.Ledger = lb.Link("/ledgers", fmt.Sprint(dest.Ledger)) - dest.Links.Operations = lb.PagedLink("/transactions", dest.ID, "operations") - dest.Links.Effects = lb.PagedLink("/transactions", dest.ID, "effects") - dest.Links.Self = lb.Link("/transactions", dest.ID) - dest.Links.Transaction = dest.Links.Self - dest.Links.Succeeds = lb.Linkf("/transactions?order=desc&cursor=%s", dest.PT) - dest.Links.Precedes = lb.Linkf("/transactions?order=asc&cursor=%s", dest.PT) - - // If we didn't need the structure, drop it. - if !tx.HasPreconditions() { - dest.Preconditions = nil - } - - return -} - -func formatSigners(s []xdr.SignerKey) []string { - if s == nil { - return nil - } - - signers := make([]string, len(s)) - for i, key := range s { - signers[i] = key.Address() - } - return signers -} - -func signatures(xdrSignatures []xdr.DecoratedSignature) []string { - signatures := make([]string, len(xdrSignatures)) - for i, sig := range xdrSignatures { - signatures[i] = base64.StdEncoding.EncodeToString(sig.Signature) - } - return signatures -} - -func memoType(tx ingester.LedgerTransaction) string { - switch tx.Envelope.Memo().Type { - case xdr.MemoTypeMemoNone: - return "none" - case xdr.MemoTypeMemoText: - return "text" - case xdr.MemoTypeMemoId: - return "id" - case xdr.MemoTypeMemoHash: - return "hash" - case xdr.MemoTypeMemoReturn: - return "return" - default: - panic(fmt.Errorf("invalid memo type: %v", tx.Envelope.Memo().Type)) - } -} - -func memo(tx ingester.LedgerTransaction) (value string, valid bool) { - valid = true - memo := tx.Envelope.Memo() - - switch memo.Type { - case xdr.MemoTypeMemoNone: - value, valid = "", false - - case xdr.MemoTypeMemoText: - scrubbed := scrub(memo.MustText()) - notnull := strings.Join(strings.Split(scrubbed, "\x00"), "") - value = notnull - - case xdr.MemoTypeMemoId: - value = fmt.Sprintf("%d", memo.MustId()) - - case xdr.MemoTypeMemoHash: - hash := memo.MustHash() - value = base64.StdEncoding.EncodeToString(hash[:]) - - case xdr.MemoTypeMemoReturn: - hash := memo.MustRetHash() - value = base64.StdEncoding.EncodeToString(hash[:]) - - default: - panic(fmt.Errorf("invalid memo type: %v", memo.Type)) - } - - return -} - -func memoBytes(envelopeXDR string) (string, error) { - var parsedEnvelope xdr.TransactionEnvelope - if err := xdr.SafeUnmarshalBase64(envelopeXDR, &parsedEnvelope); err != nil { - return "", err - } - - memo := *parsedEnvelope.Memo().Text - return base64.StdEncoding.EncodeToString([]byte(memo)), nil -} - -// scrub ensures that a given string is valid utf-8, replacing any invalid byte -// sequences with the utf-8 replacement character. -func scrub(in string) string { - // First check validity using the stdlib, returning if the string is already - // valid - if utf8.ValidString(in) { - return in - } - - left := []byte(in) - var result bytes.Buffer - - for len(left) > 0 { - r, n := utf8.DecodeRune(left) - result.WriteRune(r) // never errors, only panics - left = left[n:] - } - - return result.String() -} - -func formatTime[T constraints.Integer](t T) string { - return strconv.FormatUint(uint64(t), 10) -} diff --git a/exp/lighthorizon/adapters/transaction_test.go b/exp/lighthorizon/adapters/transaction_test.go deleted file mode 100644 index 5a8ba4ab80..0000000000 --- a/exp/lighthorizon/adapters/transaction_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package adapters - -import ( - "encoding/json" - "net/url" - "os" - "path/filepath" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/ingest" - "github.com/stellar/go/network" - protocol "github.com/stellar/go/protocols/horizon" - "github.com/stellar/go/toid" - "github.com/stellar/go/xdr" -) - -// TestTransactionAdapter confirms that the adapter correctly serializes a -// transaction to JSON by actually pulling a transaction from the -// known-to-be-true horizon.stellar.org, turning it into an "ingested" -// transaction, and serializing it. -func TestTransactionAdapter(t *testing.T) { - f, err := os.Open(filepath.Join("./testdata", "transactions.json")) - require.NoErrorf(t, err, "are fixtures missing?") - - page := protocol.TransactionsPage{} - decoder := json.NewDecoder(f) - require.NoError(t, decoder.Decode(&page)) - require.Len(t, page.Embedded.Records, 1) - expectedTx := page.Embedded.Records[0] - - parsedUrl, err := url.Parse(page.Links.Self.Href) - require.NoError(t, err) - parsedToid, err := strconv.ParseInt(expectedTx.PagingToken(), 10, 64) - require.NoError(t, err) - expectedTxIndex := toid.Parse(parsedToid).TransactionOrder - - txEnv := xdr.TransactionEnvelope{} - txResult := xdr.TransactionResult{} - txMeta := xdr.TransactionMeta{} - txFeeMeta := xdr.LedgerEntryChanges{} - - require.NoError(t, xdr.SafeUnmarshalBase64(expectedTx.EnvelopeXdr, &txEnv)) - require.NoError(t, xdr.SafeUnmarshalBase64(expectedTx.ResultMetaXdr, &txMeta)) - require.NoError(t, xdr.SafeUnmarshalBase64(expectedTx.ResultXdr, &txResult)) - require.NoError(t, xdr.SafeUnmarshalBase64(expectedTx.FeeMetaXdr, &txFeeMeta)) - - closeTimestamp := expectedTx.LedgerCloseTime.UTC().Unix() - - tx := common.Transaction{ - LedgerTransaction: &ingester.LedgerTransaction{ - LedgerTransaction: &ingest.LedgerTransaction{ - Index: 0, - Envelope: txEnv, - Result: xdr.TransactionResultPair{ - TransactionHash: xdr.Hash{}, - Result: txResult, - }, - FeeChanges: txFeeMeta, - UnsafeMeta: txMeta, - }, - }, - LedgerHeader: &xdr.LedgerHeader{ - LedgerSeq: xdr.Uint32(expectedTx.Ledger), - ScpValue: xdr.StellarValue{ - CloseTime: xdr.TimePoint(closeTimestamp), - }, - }, - TxIndex: expectedTxIndex - 1, // TOIDs have a 1-based index - NetworkPassphrase: network.PublicNetworkPassphrase, - } - - result, err := PopulateTransaction(parsedUrl, &tx, xdr.NewEncodingBuffer()) - require.NoError(t, err) - assert.Equal(t, expectedTx, result) -} diff --git a/exp/lighthorizon/build/README.md b/exp/lighthorizon/build/README.md deleted file mode 100644 index d9dcf4556d..0000000000 --- a/exp/lighthorizon/build/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Light Horizon services deployment - -Light Horizon is composed of a few micro services: -* index-batch - contains map and reduce binaries to parallize tx-meta reads and index writes. -* index-single - contains single binary that reads tx-meta and writes indexes. -* ledgerexporter - contains single binary that reads from captive core and writes tx-meta -* web - contains single binary that runs web api which reads from tx-meta and index. - -See [godoc](https://godoc.org/github.com/stellar/go/exp/lighthorizon) for details on each service. - -## Buiding docker images of each service -Each service is packaged into a Docker image, use the helper script included here to build: -`./build.sh ` - -example to build just the mydockerhubname/lighthorizon-index-single:latest image to docker local images, no push to registry: -`./build.sh index-single mydockerhubname latest false` - -example to build images for all the services and push them to mydockerhubname/lighthorizon-:testversion: -`./build.sh all mydockerhubname testversion true` - -## Deploy service images on kubernetes(k8s) -* `k8s/ledgerexporter.yml` - creates a deployment with ledgerexporter image and supporting resources, such as configmap, secret, pvc for captive core on-disk storage. Review the settings to confirm they work in your environment before deployment. -* `k8s/lighthorizon_index.yml` - creates a deployment with index-single image and supporting resources, such as configmap, secret. Review the settings to confirm they work in your environment before deployment. -* `k8s/lighthorizon_web.yml` - creates a deployment with the web image and supporting resources, such as configmap, ingress rule. Review the settings to confirm they work in your environment before deployment. diff --git a/exp/lighthorizon/build/build.sh b/exp/lighthorizon/build/build.sh deleted file mode 100755 index e884fc4914..0000000000 --- a/exp/lighthorizon/build/build.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash -e - -# Move to repo root -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$DIR/../../.." -# module name is the sub-folder name under ./build -MODULE=$1 -DOCKER_REPO_PREFIX=$2 -DOCKER_TAG=$3 -DOCKER_PUSH=$4 - -if [ -z "$MODULE" ] ||\ - [ -z "$DOCKER_REPO_PREFIX" ] ||\ - [ -z "$DOCKER_TAG" ] ||\ - [ -z "$DOCKER_PUSH" ]; then - echo "invalid parameters, requires './build.sh '" - exit 1 -fi - -build_target () { - DOCKER_LABEL="$DOCKER_REPO_PREFIX"/lighthorizon-"$MODULE":"$DOCKER_TAG" - docker build --tag $DOCKER_LABEL --platform linux/amd64 -f "exp/lighthorizon/build/$MODULE/Dockerfile" . - if [ "$DOCKER_PUSH" == "true" ]; then - docker push $DOCKER_LABEL - fi -} - -case $MODULE in -index-batch) - build_target - ;; -ledgerexporter) - build_target - ;; -index-single) - build_target - ;; -web) - build_target - ;; -all) - MODULE=index-batch - build_target - MODULE=web - build_target - MODULE=index-single - build_target - MODULE=ledgerexporter - build_target - ;; -*) - echo "unknown MODULE build parameter ('$MODULE'), must be one of all|index-batch|web|index-single|ledgerexporter" - exit 1 - ;; -esac - diff --git a/exp/lighthorizon/build/index-batch/Dockerfile b/exp/lighthorizon/build/index-batch/Dockerfile deleted file mode 100644 index 1780df682f..0000000000 --- a/exp/lighthorizon/build/index-batch/Dockerfile +++ /dev/null @@ -1,20 +0,0 @@ -FROM golang:1.20 AS builder - -WORKDIR /go/src/github.com/stellar/go -COPY . ./ -RUN go mod download -RUN go install github.com/stellar/go/exp/lighthorizon/index/cmd/batch/map -RUN go install github.com/stellar/go/exp/lighthorizon/index/cmd/batch/reduce - -FROM ubuntu:22.04 -ENV DEBIAN_FRONTEND=noninteractive -# ca-certificates are required to make tls connections -RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl wget gnupg apt-utils -RUN apt-get clean - -COPY --from=builder /go/src/github.com/stellar/go/exp/lighthorizon/build/index-batch/start ./ -COPY --from=builder /go/bin/map ./ -COPY --from=builder /go/bin/reduce ./ -RUN ["chmod", "+x", "/start"] - -ENTRYPOINT ["/start"] diff --git a/exp/lighthorizon/build/index-batch/README.md b/exp/lighthorizon/build/index-batch/README.md deleted file mode 100644 index c300066536..0000000000 --- a/exp/lighthorizon/build/index-batch/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# `stellar/lighthorizon-index-batch` - -This docker image contains the ledger/checkpoint indexing executables. It allows running multiple instances of `map`/`reduce` on a single machine or running it in [AWS Batch](https://aws.amazon.com/batch/). - -## Env variables - -See the [package documentation](../../index/cmd/batch/doc.go) for more details diff --git a/exp/lighthorizon/build/index-batch/start b/exp/lighthorizon/build/index-batch/start deleted file mode 100644 index 88fb5335fb..0000000000 --- a/exp/lighthorizon/build/index-batch/start +++ /dev/null @@ -1,17 +0,0 @@ -#! /usr/bin/env bash -set -e - -# RUN_MODE must be set to 'map' or 'reduce' - -export TRACY_NO_INVARIANT_CHECK=1 -NETWORK_PASSPHRASE="${NETWORK_PASSPHRASE:=Public Global Stellar Network ; September 2015}" -if [ "$RUN_MODE" == "reduce" ]; then - echo "Running Reduce, REDUCE JOBS: $REDUCE_JOB_COUNT MAP JOBS: $MAP_JOB_COUNT TARGET INDEX: $INDEX_TARGET" - /reduce -elif [ "$RUN_MODE" == "map" ]; then - echo "Running Map, TARGET INDEX: $INDEX_TARGET FIRST CHECKPOINT: $FIRST_CHECKPOINT" - /map -else - echo "error: undefined RUN_MODE env variable ('$RUN_MODE'), must be 'map' or 'reduce'" - exit 1 -fi diff --git a/exp/lighthorizon/build/index-single/Dockerfile b/exp/lighthorizon/build/index-single/Dockerfile deleted file mode 100644 index 1473f59f5c..0000000000 --- a/exp/lighthorizon/build/index-single/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM golang:1.20 AS builder - -WORKDIR /go/src/github.com/stellar/go -COPY . ./ -RUN go mod download -RUN go install github.com/stellar/go/exp/lighthorizon/index/cmd/single - -FROM ubuntu:22.04 - -ENV DEBIAN_FRONTEND=noninteractive -# ca-certificates are required to make tls connections -RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl wget gnupg apt-utils -RUN apt-get clean - -COPY --from=builder /go/bin/single ./ - -ENTRYPOINT ./single \ - -source "$TXMETA_SOURCE" \ - -target "$INDEXES_SOURCE" \ - -network-passphrase "$NETWORK_PASSPHRASE" \ - -start "$START" \ - -end "$END" \ - -modules "$MODULES" \ - -watch="$WATCH" \ - -workers "$WORKERS" diff --git a/exp/lighthorizon/build/k8s/ledgerexporter.yml b/exp/lighthorizon/build/k8s/ledgerexporter.yml deleted file mode 100644 index 290dd85c63..0000000000 --- a/exp/lighthorizon/build/k8s/ledgerexporter.yml +++ /dev/null @@ -1,125 +0,0 @@ -# this file contains the ledgerexporter deployment and it's config artifacts. -# -# when applying the manifest on a cluster, make sure to include namespace destination, -# as the manifest does not specify namespace, otherwise it'll go in your current kubectl context. -# -# make sure to set the secrets values, substitue placeholders. -# -# $ kubectl apply -f ledgerexporter.yml -n horizon-dev -apiVersion: v1 -kind: ConfigMap -metadata: - annotations: - fluxcd.io/ignore: "true" - labels: - app: ledgerexporter - name: ledgerexporter-pubnet-env -data: - # when using core 'on disk', the earliest ledger to get streamed out after catchup to 2, is 3 - # whereas on in-memory it streas out 2, adjusted here, otherwise horizon ingest will abort - # and stop process with error that ledger 3 is not <= expected ledger of 2. - START: "0" - END: "0" - - # can only have CONTINUE or START set, not both. - CONTINUE: "true" - WRITE_LATEST_PATH: "true" - CAPTIVE_CORE_USE_DB: "true" - - # configure the network to export - HISTORY_ARCHIVE_URLS: "https://history.stellar.org/prd/core-live/core_live_001,https://history.stellar.org/prd/core-live/core_live_002,https://history.stellar.org/prd/core-live/core_live_003" - NETWORK_PASSPHRASE: "Public Global Stellar Network ; September 2015" - # can refer to canned cfg's for pubnet and testnet which are included on the image - # `/captive-core-pubnet.cfg` or `/captive-core-testnet.cfg`. - # If exporting a standalone network, then mount a volume to the pod container with your standalone core's .cfg, - # and set full path to that volume here - CAPTIVE_CORE_CONFIG: "/captive-core-pubnet.cfg" - - # example of testnet network config. - # HISTORY_ARCHIVE_URLS: "https://history.stellar.org/prd/core-testnet/core_testnet_001,https://history.stellar.org/prd/core-testnet/core_testnet_002" - # NETWORK_PASSPHRASE: "Test SDF Network ; September 2015" - # CAPTIVE_CORE_CONFIG: "/captive-core-testnet.cfg" - - # provide the url for the external s3 bucket to be populated - # update the ledgerexporter-pubnet-secret to have correct aws key/secret for access to the bucket - ARCHIVE_TARGET: "s3://horizon-ledgermeta-prodnet-test" ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app: ledgerexporter - name: ledgerexporter-pubnet-secret -type: Opaque -data: - AWS_REGION: - AWS_ACCESS_KEY_ID: - AWS_SECRET_ACCESS_KEY: ---- -# running captive core with on-disk mode limits RAM to around 2G usage, but -# requires some dedicated disk storage space that has at least 3k IOPS for read/write. -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: ledgerexporter-pubnet-core-storage -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 500Gi - storageClassName: default - volumeMode: Filesystem ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - fluxcd.io/ignore: "true" - deployment.kubernetes.io/revision: "3" - labels: - app: ledgerexporter-pubnet - name: ledgerexporter-pubnet-deployment -spec: - selector: - matchLabels: - app: ledgerexporter-pubnet - replicas: 1 - template: - metadata: - annotations: - fluxcd.io/ignore: "true" - # if we expect to add metrics at some point to ledgerexporter - # this just needs to be set to true - prometheus.io/port: "6060" - prometheus.io/scrape: "false" - labels: - app: ledgerexporter-pubnet - spec: - containers: - - envFrom: - - secretRef: - name: ledgerexporter-pubnet-secret - - configMapRef: - name: ledgerexporter-pubnet-env - image: stellar/lighthorizon-ledgerexporter:latest - imagePullPolicy: Always - name: ledgerexporter-pubnet - resources: - limits: - cpu: 3 - memory: 8Gi - requests: - cpu: 500m - memory: 2Gi - volumeMounts: - - mountPath: /cc - name: core-storage - dnsPolicy: ClusterFirst - volumes: - - name: core-storage - persistentVolumeClaim: - claimName: ledgerexporter-pubnet-core-storage - - - diff --git a/exp/lighthorizon/build/k8s/lighthorizon_batch_map_job.yml b/exp/lighthorizon/build/k8s/lighthorizon_batch_map_job.yml deleted file mode 100644 index a2671b66c1..0000000000 --- a/exp/lighthorizon/build/k8s/lighthorizon_batch_map_job.yml +++ /dev/null @@ -1,43 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: 'batch-map-job' -spec: - completions: 52 - parallelism: 10 - completionMode: Indexed - template: - spec: - restartPolicy: Never - containers: - - name: 'worker' - image: 'stellar/lighthorizon-index-batch' - imagePullPolicy: Always - envFrom: - - secretRef: - name: - env: - - name: RUN_MODE - value: "map" - - name: BATCH_SIZE - value: "10048" - - name: FIRST_CHECKPOINT - value: "41426080" - - name: WORKER_COUNT - value: "8" - - name: TXMETA_SOURCE - value: "" - - name: JOB_INDEX_ENV - value: "JOB_COMPLETION_INDEX" - - name: NETWORK_PASSPHRASE - value: "pubnet" - - name: INDEX_TARGET - value: "url of target index" - resources: - limits: - cpu: 4 - memory: 5Gi - requests: - cpu: 500m - memory: 500Mi - \ No newline at end of file diff --git a/exp/lighthorizon/build/k8s/lighthorizon_batch_reduce_job.yml b/exp/lighthorizon/build/k8s/lighthorizon_batch_reduce_job.yml deleted file mode 100644 index 1bc9cb7f6c..0000000000 --- a/exp/lighthorizon/build/k8s/lighthorizon_batch_reduce_job.yml +++ /dev/null @@ -1,42 +0,0 @@ -apiVersion: batch/v1 -kind: Job -metadata: - name: 'batch-reduce-job' -spec: - completions: 52 - parallelism: 10 - completionMode: Indexed - template: - spec: - restartPolicy: Never - containers: - - name: 'worker' - image: 'stellar/lighthorizon-index-batch' - imagePullPolicy: Always - envFrom: - - secretRef: - name: - env: - - name: RUN_MODE - value: "reduce" - - name: MAP_JOB_COUNT - value: "52" - - name: REDUCE_JOB_COUNT - value: "52" - - name: WORKER_COUNT - value: "8" - - name: INDEX_SOURCE_ROOT - value: "" - - name: JOB_INDEX_ENV - value: JOB_COMPLETION_INDEX - - name: INDEX_TARGET - value: "" - resources: - limits: - cpu: 4 - memory: 5Gi - requests: - cpu: 500m - memory: 500Mi - - \ No newline at end of file diff --git a/exp/lighthorizon/build/k8s/lighthorizon_index.yml b/exp/lighthorizon/build/k8s/lighthorizon_index.yml deleted file mode 100644 index 1e7931fb2a..0000000000 --- a/exp/lighthorizon/build/k8s/lighthorizon_index.yml +++ /dev/null @@ -1,74 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - annotations: - fluxcd.io/ignore: "true" - labels: - app: lighthorizon-pubnet-index - name: lighthorizon-pubnet-index-env -data: - TXMETA_SOURCE: "s3://horizon-ledgermeta-prodnet-test" - INDEXES_SOURCE: "s3://horizon-index-prodnet-test" - NETWORK_PASSPHRASE: "Public Global Stellar Network ; September 2015" - START: "41809728" - END: "0" - WATCH: "true" - MODULES: "accounts" - WORKERS: "3" ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app: lighthorizon-pubnet-index - name: lighthorizon-pubnet-index-secret -type: Opaque -data: - AWS_REGION: - AWS_ACCESS_KEY_ID: - AWS_SECRET_ACCESS_KEY: ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - fluxcd.io/ignore: "true" - labels: - app: lighthorizon-pubnet-index - name: lighthorizon-pubnet-index -spec: - replicas: 1 - selector: - matchLabels: - app: lighthorizon-pubnet-index - template: - metadata: - annotations: - fluxcd.io/ignore: "true" - prometheus.io/port: "6060" - prometheus.io/scrape: "false" - labels: - app: lighthorizon-pubnet-index - spec: - containers: - - envFrom: - - secretRef: - name: lighthorizon-pubnet-index-secret - - configMapRef: - name: lighthorizon-pubnet-index-env - image: stellar/lighthorizon-index-single:latest - imagePullPolicy: Always - name: index - ports: - - containerPort: 6060 - name: metrics - protocol: TCP - resources: - limits: - cpu: 3 - memory: 6Gi - requests: - cpu: 500m - memory: 1Gi - - \ No newline at end of file diff --git a/exp/lighthorizon/build/k8s/lighthorizon_web.yml b/exp/lighthorizon/build/k8s/lighthorizon_web.yml deleted file mode 100644 index b680e7fb2c..0000000000 --- a/exp/lighthorizon/build/k8s/lighthorizon_web.yml +++ /dev/null @@ -1,133 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - annotations: - fluxcd.io/ignore: "true" - labels: - app: lighthorizon-pubnet-web - name: lighthorizon-pubnet-web-env -data: - TXMETA_SOURCE: "s3://horizon-indices-pubnet" - INDEXES_SOURCE: "s3://horizon-ledgermeta-pubnet" - NETWORK_PASSPHRASE: "Public Global Stellar Network ; September 2015" - MAX_PARALLEL_DOWNLOADS: 16 - CACHE_PATH: "/ledgercache" - CACHE_PRELOAD_START_LEDGER: 0 - CACHE_PRELOAD_COUNT: 14400 ---- -apiVersion: v1 -kind: Secret -metadata: - labels: - app: lighthorizon-pubnet-web - name: lighthorizon-pubnet-web-secret -type: Opaque -data: - AWS_REGION: - AWS_ACCESS_KEY_ID: - AWS_SECRET_ACCESS_KEY: ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - fluxcd.io/ignore: "true" - labels: - app: lighthorizon-pubnet-web - name: lighthorizon-pubnet-web -spec: - replicas: 1 - selector: - matchLabels: - app: lighthorizon-pubnet-web - template: - metadata: - annotations: - fluxcd.io/ignore: "true" - prometheus.io/port: "6060" - prometheus.io/scrape: "false" - creationTimestamp: null - labels: - app: lighthorizon-pubnet-web - spec: - containers: - - envFrom: - - secretRef: - name: lighthorizon-pubnet-web-secret - - configMapRef: - name: lighthorizon-pubnet-web-env - image: stellar/lighthorizon-web:latest - imagePullPolicy: Always - name: web - ports: - - containerPort: 8080 - name: web - protocol: TCP - - containerPort: 6060 - name: metrics - protocol: TCP - readinessProbe: - failureThreshold: 3 - httpGet: - path: / - port: 8080 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 30 - successThreshold: 1 - timeoutSeconds: 5 - resources: - limits: - cpu: 2 - memory: 4Gi - requests: - cpu: 500m - memory: 1Gi - volumeMounts: - - mountPath: /ledgercache - name: cache-storage - volumes: - - name: cache-storage - emptyDir: {} ---- -apiVersion: v1 -kind: Service -metadata: - labels: - app: lighthorizon-pubnet-web - name: lighthorizon-pubnet-web -spec: - ports: - - name: http - port: 8000 - protocol: TCP - targetPort: 8080 - selector: - app: lighthorizon-pubnet-web - sessionAffinity: None - type: ClusterIP ---- -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - cert-manager.io/cluster-issuer: default - ingress.kubernetes.io/ssl-redirect: "true" - kubernetes.io/ingress.class: public - name: lighthorizon-pubnet-web -spec: - rules: - - host: lighthorizon-pubnet.prototypes.kube001.services.stellar-ops.com - http: - paths: - - backend: - service: - name: lighthorizon-pubnet-web - port: - number: 8000 - path: / - pathType: ImplementationSpecific - tls: - - hosts: - - lighthorizon-pubnet.prototypes.kube001.services.stellar-ops.com - secretName: lighthorizon-pubnet-web-cert diff --git a/exp/lighthorizon/build/ledgerexporter/Dockerfile b/exp/lighthorizon/build/ledgerexporter/Dockerfile deleted file mode 100644 index f7129d7be2..0000000000 --- a/exp/lighthorizon/build/ledgerexporter/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM golang:1.20 AS builder - -WORKDIR /go/src/github.com/stellar/go -COPY . ./ -RUN go mod download -RUN go install github.com/stellar/go/exp/services/ledgerexporter - -FROM ubuntu:22.04 -ARG STELLAR_CORE_VERSION -ENV STELLAR_CORE_VERSION=${STELLAR_CORE_VERSION:-*} -ENV STELLAR_CORE_BINARY_PATH /usr/bin/stellar-core - -ENV DEBIAN_FRONTEND=noninteractive -# ca-certificates are required to make tls connections -RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl wget gnupg apt-utils -RUN wget -qO - https://apt.stellar.org/SDF.asc | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=true apt-key add - -RUN echo "deb https://apt.stellar.org jammy stable" >/etc/apt/sources.list.d/SDF.list -RUN echo "deb https://apt.stellar.org jammy unstable" >/etc/apt/sources.list.d/SDF-unstable.list -RUN apt-get update && apt-get install -y stellar-core=${STELLAR_CORE_VERSION} -RUN apt-get clean - -COPY --from=builder /go/src/github.com/stellar/go/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg / -COPY --from=builder /go/src/github.com/stellar/go/exp/lighthorizon/build/ledgerexporter/captive-core-testnet.cfg / -COPY --from=builder /go/src/github.com/stellar/go/exp/lighthorizon/build/ledgerexporter/start / - -RUN ["chmod", "+x", "/start"] - -# for the captive core sqlite database -RUN mkdir -p /cc - -COPY --from=builder /go/bin/ledgerexporter ./ - -ENTRYPOINT ["/start"] diff --git a/exp/lighthorizon/build/ledgerexporter/README.md b/exp/lighthorizon/build/ledgerexporter/README.md deleted file mode 100644 index 5534b2809a..0000000000 --- a/exp/lighthorizon/build/ledgerexporter/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# `stellar/horizon-ledgerexporter` - -This docker image allows running multiple instances of `ledgerexporter` on a single machine or running it in [AWS Batch](https://aws.amazon.com/batch/). - -## Env variables - -### Running locally - -| Name | Description | -|---------|------------------------| -| `START` | First ledger to export | -| `END` | Last ledger to export | - -### Running in AWS Batch - -| Name | Description | -|----------------------|----------------------------------------------------------------------| -| `BATCH_START_LEDGER` | First ledger of the AWS Batch Job, must be a checkpoint ledger or 1. | -| `BATCH_SIZE` | Size of the batch, must be multiple of 64. | - -#### Example - -When you start 10 jobs with `BATCH_START_LEDGER=63` and `BATCH_SIZE=64` -it will run the following ranges: - -| `AWS_BATCH_JOB_ARRAY_INDEX` | `FROM` | `TO` | -|-----------------------------|--------|------| -| 0 | 63 | 127 | -| 1 | 127 | 191 | -| 2 | 191 | 255 | -| 3 | 255 | 319 | - -## Tips when using AWS Batch - -* In "Job definition" set vCPUs to 2 and Memory to 4096. This represents the `c5.large` instances Horizon should be using. -* In "Compute environments": - * Set instance type to "c5.large". - * Set "Maximum vCPUs" to 2x the number of instances you want to start (because "c5.large" has 2 vCPUs). Ex. 10 vCPUs = 5 x "c5.large" instances. -* Use spot instances! It's much cheaper and speed of testing will be the same in 99% of cases. -* You need to publish the image if there are any changes in `Dockerfile` or one of the scripts. -* When batch processing is over check if instances have been terminated. Sometimes AWS doesn't terminate them. -* Make sure the job timeout is set to a larger value if you export larger ranges. Default is just 100 seconds. diff --git a/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg b/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg deleted file mode 100644 index 6379725b8d..0000000000 --- a/exp/lighthorizon/build/ledgerexporter/captive-core-pubnet.cfg +++ /dev/null @@ -1,200 +0,0 @@ -PEER_PORT=11725 -DATABASE = "sqlite3:///cc/stellar.db" - -FAILURE_SAFETY=1 - -EXPERIMENTAL_BUCKETLIST_DB=true - -# WARNING! Do not use this config in production. Quorum sets should -# be carefully selected manually. -NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015" -HTTP_PORT=11626 - -[[HOME_DOMAINS]] -HOME_DOMAIN="publicnode.org" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="lobstr.co" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="www.franklintempleton.com" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="satoshipay.io" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="whalestack.com" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="www.stellar.org" -QUALITY="HIGH" - -[[HOME_DOMAINS]] -HOME_DOMAIN="stellar.blockdaemon.com" -QUALITY="HIGH" - -[[VALIDATORS]] -NAME="Boötes" -PUBLIC_KEY="GCVJ4Z6TI6Z2SOGENSPXDQ2U4RKH3CNQKYUHNSSPYFPNWTLGS6EBH7I2" -ADDRESS="bootes.publicnode.org:11625" -HISTORY="curl -sf https://bootes-history.publicnode.org/{0} -o {1}" -HOME_DOMAIN="publicnode.org" - -[[VALIDATORS]] -NAME="Lyra by BP Ventures" -PUBLIC_KEY="GCIXVKNFPKWVMKJKVK2V4NK7D4TC6W3BUMXSIJ365QUAXWBRPPJXIR2Z" -ADDRESS="lyra.publicnode.org:11625" -HISTORY="curl -sf https://lyra-history.publicnode.org/{0} -o {1}" -HOME_DOMAIN="publicnode.org" - -[[VALIDATORS]] -NAME="Hercules by OG Technologies" -PUBLIC_KEY="GBLJNN3AVZZPG2FYAYTYQKECNWTQYYUUY2KVFN2OUKZKBULXIXBZ4FCT" -ADDRESS="hercules.publicnode.org:11625" -HISTORY="curl -sf https://hercules-history.publicnode.org/{0} -o {1}" -HOME_DOMAIN="publicnode.org" - -[[VALIDATORS]] -NAME="LOBSTR 3 (North America)" -PUBLIC_KEY="GD5QWEVV4GZZTQP46BRXV5CUMMMLP4JTGFD7FWYJJWRL54CELY6JGQ63" -ADDRESS="v3.stellar.lobstr.co:11625" -HISTORY="curl -sf https://archive.v3.stellar.lobstr.co/{0} -o {1}" -HOME_DOMAIN="lobstr.co" - -[[VALIDATORS]] -NAME="LOBSTR 1 (Europe)" -PUBLIC_KEY="GCFONE23AB7Y6C5YZOMKUKGETPIAJA4QOYLS5VNS4JHBGKRZCPYHDLW7" -ADDRESS="v1.stellar.lobstr.co:11625" -HISTORY="curl -sf https://archive.v1.stellar.lobstr.co/{0} -o {1}" -HOME_DOMAIN="lobstr.co" - -[[VALIDATORS]] -NAME="LOBSTR 2 (Europe)" -PUBLIC_KEY="GCB2VSADESRV2DDTIVTFLBDI562K6KE3KMKILBHUHUWFXCUBHGQDI7VL" -ADDRESS="v2.stellar.lobstr.co:11625" -HISTORY="curl -sf https://archive.v2.stellar.lobstr.co/{0} -o {1}" -HOME_DOMAIN="lobstr.co" - -[[VALIDATORS]] -NAME="LOBSTR 4 (Asia)" -PUBLIC_KEY="GA7TEPCBDQKI7JQLQ34ZURRMK44DVYCIGVXQQWNSWAEQR6KB4FMCBT7J" -ADDRESS="v4.stellar.lobstr.co:11625" -HISTORY="curl -sf https://archive.v4.stellar.lobstr.co/{0} -o {1}" -HOME_DOMAIN="lobstr.co" - -[[VALIDATORS]] -NAME="LOBSTR 5 (India)" -PUBLIC_KEY="GA5STBMV6QDXFDGD62MEHLLHZTPDI77U3PFOD2SELU5RJDHQWBR5NNK7" -ADDRESS="v5.stellar.lobstr.co:11625" -HISTORY="curl -sf https://archive.v5.stellar.lobstr.co/{0} -o {1}" -HOME_DOMAIN="lobstr.co" - -[[VALIDATORS]] -NAME="FT SCV 2" -PUBLIC_KEY="GCMSM2VFZGRPTZKPH5OABHGH4F3AVS6XTNJXDGCZ3MKCOSUBH3FL6DOB" -ADDRESS="stellar2.franklintempleton.com:11625" -HISTORY="curl -sf https://stellar-history-usc.franklintempleton.com/azuscshf401/{0} -o {1}" -HOME_DOMAIN="www.franklintempleton.com" - -[[VALIDATORS]] -NAME="FT SCV 3" -PUBLIC_KEY="GA7DV63PBUUWNUFAF4GAZVXU2OZMYRATDLKTC7VTCG7AU4XUPN5VRX4A" -ADDRESS="stellar3.franklintempleton.com:11625" -HISTORY="curl -sf https://stellar-history-ins.franklintempleton.com/azinsshf401/{0} -o {1}" -HOME_DOMAIN="www.franklintempleton.com" - -[[VALIDATORS]] -NAME="FT SCV 1" -PUBLIC_KEY="GARYGQ5F2IJEBCZJCBNPWNWVDOFK7IBOHLJKKSG2TMHDQKEEC6P4PE4V" -ADDRESS="stellar1.franklintempleton.com:11625" -HISTORY="curl -sf https://stellar-history-usw.franklintempleton.com/azuswshf401/{0} -o {1}" -HOME_DOMAIN="www.franklintempleton.com" - -[[VALIDATORS]] -NAME="SatoshiPay Frankfurt" -PUBLIC_KEY="GC5SXLNAM3C4NMGK2PXK4R34B5GNZ47FYQ24ZIBFDFOCU6D4KBN4POAE" -ADDRESS="stellar-de-fra.satoshipay.io:11625" -HISTORY="curl -sf https://stellar-history-de-fra.satoshipay.io/{0} -o {1}" -HOME_DOMAIN="satoshipay.io" - -[[VALIDATORS]] -NAME="SatoshiPay Singapore" -PUBLIC_KEY="GBJQUIXUO4XSNPAUT6ODLZUJRV2NPXYASKUBY4G5MYP3M47PCVI55MNT" -ADDRESS="stellar-sg-sin.satoshipay.io:11625" -HISTORY="curl -sf https://stellar-history-sg-sin.satoshipay.io/{0} -o {1}" -HOME_DOMAIN="satoshipay.io" - -[[VALIDATORS]] -NAME="SatoshiPay Iowa" -PUBLIC_KEY="GAK6Z5UVGUVSEK6PEOCAYJISTT5EJBB34PN3NOLEQG2SUKXRVV2F6HZY" -ADDRESS="stellar-us-iowa.satoshipay.io:11625" -HISTORY="curl -sf https://stellar-history-us-iowa.satoshipay.io/{0} -o {1}" -HOME_DOMAIN="satoshipay.io" - -[[VALIDATORS]] -NAME="Whalestack (Germany)" -PUBLIC_KEY="GD6SZQV3WEJUH352NTVLKEV2JM2RH266VPEM7EH5QLLI7ZZAALMLNUVN" -ADDRESS="germany.stellar.whalestack.com:11625" -HISTORY="curl -sf https://germany.stellar.whalestack.com/history/{0} -o {1}" -HOME_DOMAIN="whalestack.com" - -[[VALIDATORS]] -NAME="Whalestack (Hong Kong)" -PUBLIC_KEY="GAZ437J46SCFPZEDLVGDMKZPLFO77XJ4QVAURSJVRZK2T5S7XUFHXI2Z" -ADDRESS="hongkong.stellar.whalestack.com:11625" -HISTORY="curl -sf https://hongkong.stellar.whalestack.com/history/{0} -o {1}" -HOME_DOMAIN="whalestack.com" - -[[VALIDATORS]] -NAME="Whalestack (Finland)" -PUBLIC_KEY="GADLA6BJK6VK33EM2IDQM37L5KGVCY5MSHSHVJA4SCNGNUIEOTCR6J5T" -ADDRESS="finland.stellar.whalestack.com:11625" -HISTORY="curl -sf https://finland.stellar.whalestack.com/history/{0} -o {1}" -HOME_DOMAIN="whalestack.com" - -[[VALIDATORS]] -NAME="SDF 2" -PUBLIC_KEY="GCM6QMP3DLRPTAZW2UZPCPX2LF3SXWXKPMP3GKFZBDSF3QZGV2G5QSTK" -ADDRESS="core-live-b.stellar.org:11625" -HISTORY="curl -sf http://history.stellar.org/prd/core-live/core_live_002/{0} -o {1}" -HOME_DOMAIN="www.stellar.org" - -[[VALIDATORS]] -NAME="SDF 1" -PUBLIC_KEY="GCGB2S2KGYARPVIA37HYZXVRM2YZUEXA6S33ZU5BUDC6THSB62LZSTYH" -ADDRESS="core-live-a.stellar.org:11625" -HISTORY="curl -sf http://history.stellar.org/prd/core-live/core_live_001/{0} -o {1}" -HOME_DOMAIN="www.stellar.org" - -[[VALIDATORS]] -NAME="SDF 3" -PUBLIC_KEY="GABMKJM6I25XI4K7U6XWMULOUQIQ27BCTMLS6BYYSOWKTBUXVRJSXHYQ" -ADDRESS="core-live-c.stellar.org:11625" -HISTORY="curl -sf http://history.stellar.org/prd/core-live/core_live_003/{0} -o {1}" -HOME_DOMAIN="www.stellar.org" - -[[VALIDATORS]] -NAME="Blockdaemon Validator 3" -PUBLIC_KEY="GAYXZ4PZ7P6QOX7EBHPIZXNWY4KCOBYWJCA4WKWRKC7XIUS3UJPT6EZ4" -ADDRESS="stellar-full-validator3.bdnodes.net:11625" -HISTORY="curl -sf https://stellar-full-history3.bdnodes.net/{0} -o {1}" -HOME_DOMAIN="stellar.blockdaemon.com" - -[[VALIDATORS]] -NAME="Blockdaemon Validator 2" -PUBLIC_KEY="GAVXB7SBJRYHSG6KSQHY74N7JAFRL4PFVZCNWW2ARI6ZEKNBJSMSKW7C" -ADDRESS="stellar-full-validator2.bdnodes.net:11625" -HISTORY="curl -sf https://stellar-full-history2.bdnodes.net/{0} -o {1}" -HOME_DOMAIN="stellar.blockdaemon.com" - -[[VALIDATORS]] -NAME="Blockdaemon Validator 1" -PUBLIC_KEY="GAAV2GCVFLNN522ORUYFV33E76VPC22E72S75AQ6MBR5V45Z5DWVPWEU" -ADDRESS="stellar-full-validator1.bdnodes.net:11625" -HISTORY="curl -sf https://stellar-full-history1.bdnodes.net/{0} -o {1}" -HOME_DOMAIN="stellar.blockdaemon.com" \ No newline at end of file diff --git a/exp/lighthorizon/build/ledgerexporter/captive-core-testnet.cfg b/exp/lighthorizon/build/ledgerexporter/captive-core-testnet.cfg deleted file mode 100644 index 9c7dadc527..0000000000 --- a/exp/lighthorizon/build/ledgerexporter/captive-core-testnet.cfg +++ /dev/null @@ -1,32 +0,0 @@ -PEER_PORT=11725 -DATABASE = "sqlite3:///cc/stellar.db" - -UNSAFE_QUORUM=true -FAILURE_SAFETY=1 - -EXPERIMENTAL_BUCKETLIST_DB=true - -[[HOME_DOMAINS]] -HOME_DOMAIN="testnet.stellar.org" -QUALITY="HIGH" - -[[VALIDATORS]] -NAME="sdf_testnet_1" -HOME_DOMAIN="testnet.stellar.org" -PUBLIC_KEY="GDKXE2OZMJIPOSLNA6N6F2BVCI3O777I2OOC4BV7VOYUEHYX7RTRYA7Y" -ADDRESS="core-testnet1.stellar.org" -HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_001/{0} -o {1}" - -[[VALIDATORS]] -NAME="sdf_testnet_2" -HOME_DOMAIN="testnet.stellar.org" -PUBLIC_KEY="GCUCJTIYXSOXKBSNFGNFWW5MUQ54HKRPGJUTQFJ5RQXZXNOLNXYDHRAP" -ADDRESS="core-testnet2.stellar.org" -HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_002/{0} -o {1}" - -[[VALIDATORS]] -NAME="sdf_testnet_3" -HOME_DOMAIN="testnet.stellar.org" -PUBLIC_KEY="GC2V2EFSXN6SQTWVYA5EPJPBWWIMSD2XQNKUOHGEKB535AQE2I6IXV2Z" -ADDRESS="core-testnet3.stellar.org" -HISTORY="curl -sf http://history.stellar.org/prd/core-testnet/core_testnet_003/{0} -o {1}" \ No newline at end of file diff --git a/exp/lighthorizon/build/ledgerexporter/start b/exp/lighthorizon/build/ledgerexporter/start deleted file mode 100644 index 11d863effa..0000000000 --- a/exp/lighthorizon/build/ledgerexporter/start +++ /dev/null @@ -1,55 +0,0 @@ -#! /usr/bin/env bash -set -e - -START="${START:=2}" -END="${END:=0}" -CONTINUE="${CONTINUE:=false}" -# Writing to /latest is disabled by default to avoid race conditions between parallel container runs -WRITE_LATEST_PATH="${WRITE_LATEST_PATH:=false}" - -# config defaults to pubnet core, any other network requires setting all 3 of these in container env -NETWORK_PASSPHRASE="${NETWORK_PASSPHRASE:=Public Global Stellar Network ; September 2015}" -HISTORY_ARCHIVE_URLS="${HISTORY_ARCHIVE_URLS:=https://s3-eu-west-1.amazonaws.com/history.stellar.org/prd/core-live/core_live_001}" -CAPTIVE_CORE_CONFIG="${CAPTIVE_CORE_CONFIG:=/captive-core-pubnet.cfg}" - -CAPTIVE_CORE_USE_DB="${CAPTIVE_CORE_USE_DB:=true}" - -if [ -z "$ARCHIVE_TARGET" ]; then - echo "error: undefined ARCHIVE_TARGET env variable" - exit 1 -fi - -# Calculate params for AWS Batch -if [ ! -z "$AWS_BATCH_JOB_ARRAY_INDEX" ]; then - # The batch should have three env variables: - # * BATCH_START_LEDGER - start ledger of the job, must be equal 1 or a - # checkpoint ledger (i + 1) % 64 == 0. - # * BATCH_SIZE - size of the batch in ledgers, must be multiple of 64! - # * BRANCH - git branch to build - # - # Ex: BATCH_START_LEDGER=63, BATCH_SIZE=64 will create the following ranges: - # AWS_BATCH_JOB_ARRAY_INDEX=0: [63, 127] - # AWS_BATCH_JOB_ARRAY_INDEX=1: [127, 191] - # AWS_BATCH_JOB_ARRAY_INDEX=2: [191, 255] - # AWS_BATCH_JOB_ARRAY_INDEX=3: [255, 319] - # ... - START=`expr "$BATCH_SIZE" \* "$AWS_BATCH_JOB_ARRAY_INDEX" + "$BATCH_START_LEDGER"` - END=`expr "$BATCH_SIZE" \* "$AWS_BATCH_JOB_ARRAY_INDEX" + "$BATCH_START_LEDGER" + "$BATCH_SIZE"` - - if [ "$START" -lt 2 ]; then - # The minimum ledger expected by the ledger exporter is 2 - START=2 - fi - -fi - -echo "START: $START END: $END" - -export TRACY_NO_INVARIANT_CHECK=1 -/ledgerexporter --target "$ARCHIVE_TARGET" \ - --captive-core-toml-path "$CAPTIVE_CORE_CONFIG" \ - --history-archive-urls "$HISTORY_ARCHIVE_URLS" --network-passphrase "$NETWORK_PASSPHRASE" \ - --continue="$CONTINUE" --write-latest-path="$WRITE_LATEST_PATH" \ - --start-ledger "$START" --end-ledger "$END" --captive-core-use-db="$CAPTIVE_CORE_USE_DB" - -echo "OK" diff --git a/exp/lighthorizon/build/web/Dockerfile b/exp/lighthorizon/build/web/Dockerfile deleted file mode 100644 index 83d0002ebc..0000000000 --- a/exp/lighthorizon/build/web/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM golang:1.20 AS builder - -WORKDIR /go/src/github.com/stellar/go -COPY . ./ -RUN go mod download -RUN go install github.com/stellar/go/exp/lighthorizon - -FROM ubuntu:22.04 - -ENV DEBIAN_FRONTEND=noninteractive -# ca-certificates are required to make tls connections -RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates curl wget gnupg apt-utils -RUN apt-get clean - -COPY --from=builder /go/bin/lighthorizon ./ - -ENTRYPOINT ./lighthorizon serve \ - --network-passphrase "$NETWORK_PASSPHRASE" \ - --parallel-downloads "$MAX_PARALLEL_DOWNLOADS" \ - --ledger-cache "$CACHE_PATH" \ - --ledger-cache-preload "$CACHE_PRELOAD_COUNT" \ - --ledger-cache-preload-start "$CACHE_PRELOAD_START_LEDGER" \ - --log-level debug \ - "$TXMETA_SOURCE" "$INDEXES_SOURCE" diff --git a/exp/lighthorizon/common/operation.go b/exp/lighthorizon/common/operation.go deleted file mode 100644 index ca5f7bfe61..0000000000 --- a/exp/lighthorizon/common/operation.go +++ /dev/null @@ -1,52 +0,0 @@ -package common - -import ( - "encoding/hex" - - "github.com/stellar/go/network" - "github.com/stellar/go/toid" - "github.com/stellar/go/xdr" -) - -type Operation struct { - TransactionEnvelope *xdr.TransactionEnvelope - TransactionResult *xdr.TransactionResult - LedgerHeader *xdr.LedgerHeader - OpIndex int32 - TxIndex int32 -} - -func (o *Operation) Get() *xdr.Operation { - return &o.TransactionEnvelope.Operations()[o.OpIndex] -} - -func (o *Operation) OperationResult() *xdr.OperationResultTr { - results, _ := o.TransactionResult.OperationResults() - tr := results[o.OpIndex].MustTr() - return &tr -} - -func (o *Operation) TransactionHash() (string, error) { - hash, err := network.HashTransactionInEnvelope(*o.TransactionEnvelope, network.PublicNetworkPassphrase) - if err != nil { - return "", err - } - - return hex.EncodeToString(hash[:]), nil -} - -func (o *Operation) SourceAccount() xdr.AccountId { - sourceAccount := o.TransactionEnvelope.SourceAccount().ToAccountId() - if o.Get().SourceAccount != nil { - sourceAccount = o.Get().SourceAccount.ToAccountId() - } - return sourceAccount -} - -func (o *Operation) TOID() int64 { - return toid.New( - int32(o.LedgerHeader.LedgerSeq), - o.TxIndex+1, - o.OpIndex+1, - ).ToInt64() -} diff --git a/exp/lighthorizon/common/transaction.go b/exp/lighthorizon/common/transaction.go deleted file mode 100644 index 104fd3bc6b..0000000000 --- a/exp/lighthorizon/common/transaction.go +++ /dev/null @@ -1,70 +0,0 @@ -package common - -import ( - "encoding/hex" - "errors" - - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/network" - "github.com/stellar/go/toid" - "github.com/stellar/go/xdr" -) - -type Transaction struct { - *ingester.LedgerTransaction - LedgerHeader *xdr.LedgerHeader - TxIndex int32 - - NetworkPassphrase string -} - -// type Transaction struct { -// TransactionEnvelope *xdr.TransactionEnvelope -// TransactionResult *xdr.TransactionResult -// } - -func (tx *Transaction) TransactionHash() (string, error) { - if tx.NetworkPassphrase == "" { - return "", errors.New("network passphrase unspecified") - } - - hash, err := network.HashTransactionInEnvelope(tx.Envelope, tx.NetworkPassphrase) - if err != nil { - return "", err - } - - return hex.EncodeToString(hash[:]), nil -} - -func (o *Transaction) SourceAccount() xdr.MuxedAccount { - return o.Envelope.SourceAccount() -} - -func (tx *Transaction) TOID() int64 { - return toid.New( - int32(tx.LedgerHeader.LedgerSeq), - // TOID indexing is 1-based, so the 1st tx comes at position 1, - tx.TxIndex+1, - // but the TOID of a transaction comes BEFORE any operation - 0, - ).ToInt64() -} - -func (tx *Transaction) HasPreconditions() bool { - switch pc := tx.Envelope.Preconditions(); pc.Type { - case xdr.PreconditionTypePrecondNone: - return false - case xdr.PreconditionTypePrecondTime: - return pc.TimeBounds != nil - case xdr.PreconditionTypePrecondV2: - // TODO: 2x check these - return (pc.V2.TimeBounds != nil || - pc.V2.LedgerBounds != nil || - pc.V2.MinSeqNum != nil || - pc.V2.MinSeqAge > 0 || - pc.V2.MinSeqLedgerGap > 0 || - len(pc.V2.ExtraSigners) > 0) - } - - return false -} diff --git a/exp/lighthorizon/http.go b/exp/lighthorizon/http.go deleted file mode 100644 index e61ad4c716..0000000000 --- a/exp/lighthorizon/http.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "net/http" - "strconv" - "time" - - "github.com/go-chi/chi" - "github.com/go-chi/chi/middleware" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/promhttp" - - "github.com/stellar/go/exp/lighthorizon/actions" - "github.com/stellar/go/exp/lighthorizon/services" - supportHttp "github.com/stellar/go/support/http" - "github.com/stellar/go/support/render/problem" -) - -func newWrapResponseWriter(w http.ResponseWriter, r *http.Request) middleware.WrapResponseWriter { - mw, ok := w.(middleware.WrapResponseWriter) - if !ok { - mw = middleware.NewWrapResponseWriter(w, r.ProtoMajor) - } - - return mw -} - -func prometheusMiddleware(requestDurationMetric *prometheus.SummaryVec) func(next http.Handler) http.Handler { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - route := supportHttp.GetChiRoutePattern(r) - mw := newWrapResponseWriter(w, r) - - then := time.Now() - next.ServeHTTP(mw, r) - duration := time.Since(then) - - requestDurationMetric.With(prometheus.Labels{ - "status": strconv.FormatInt(int64(mw.Status()), 10), - "method": r.Method, - "route": route, - }).Observe(float64(duration.Seconds())) - }) - } -} - -func lightHorizonHTTPHandler(registry *prometheus.Registry, lightHorizon services.LightHorizon) http.Handler { - requestDurationMetric := prometheus.NewSummaryVec( - prometheus.SummaryOpts{ - Namespace: "horizon_lite", Subsystem: "http", Name: "requests_duration_seconds", - Help: "HTTP requests durations, sliding window = 10m", - }, - []string{"status", "method", "route"}, - ) - registry.MustRegister(requestDurationMetric) - - router := chi.NewMux() - router.Use(prometheusMiddleware(requestDurationMetric)) - - router.Route("/accounts/{account_id}", func(r chi.Router) { - r.MethodFunc(http.MethodGet, "/transactions", actions.NewTXByAccountHandler(lightHorizon)) - r.MethodFunc(http.MethodGet, "/operations", actions.NewOpsByAccountHandler(lightHorizon)) - }) - - router.MethodFunc(http.MethodGet, "/", actions.Root(actions.RootResponse{ - Version: HorizonLiteVersion, - // by default, no other fields are known yet - })) - router.MethodFunc(http.MethodGet, "/api", actions.ApiDocs()) - router.Method(http.MethodGet, "/metrics", promhttp.HandlerFor(registry, promhttp.HandlerOpts{})) - - problem.RegisterHost("") - router.NotFound(func(w http.ResponseWriter, request *http.Request) { - problem.Render(request.Context(), w, problem.NotFound) - }) - - return router -} diff --git a/exp/lighthorizon/http_test.go b/exp/lighthorizon/http_test.go deleted file mode 100644 index f59e2719d5..0000000000 --- a/exp/lighthorizon/http_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "testing" - - "github.com/prometheus/client_golang/prometheus" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/stellar/go/exp/lighthorizon/actions" - "github.com/stellar/go/exp/lighthorizon/services" - "github.com/stellar/go/support/render/problem" -) - -func TestUnknownUrl(t *testing.T) { - recorder := httptest.NewRecorder() - request, err := http.NewRequest("GET", "/unknown", nil) - require.NoError(t, err) - - prepareTestHttpHandler().ServeHTTP(recorder, request) - - resp := recorder.Result() - assert.Equal(t, http.StatusNotFound, resp.StatusCode) - - raw, err := io.ReadAll(resp.Body) - assert.NoError(t, err) - - var problem problem.P - err = json.Unmarshal(raw, &problem) - assert.NoError(t, err) - assert.Equal(t, "Resource Missing", problem.Title) - assert.Equal(t, "not_found", problem.Type) -} - -func TestRootResponse(t *testing.T) { - recorder := httptest.NewRecorder() - request, err := http.NewRequest("GET", "/", nil) - require.NoError(t, err) - - prepareTestHttpHandler().ServeHTTP(recorder, request) - - var root actions.RootResponse - raw, err := io.ReadAll(recorder.Result().Body) - require.NoError(t, err) - require.NoError(t, json.Unmarshal(raw, &root)) - require.Equal(t, HorizonLiteVersion, root.Version) -} - -func prepareTestHttpHandler() http.Handler { - mockOperationService := &services.MockOperationService{} - mockTransactionService := &services.MockTransactionService{} - registry := prometheus.NewRegistry() - - lh := services.LightHorizon{ - Operations: mockOperationService, - Transactions: mockTransactionService, - } - - return lightHorizonHTTPHandler(registry, lh) -} diff --git a/exp/lighthorizon/index/Makefile b/exp/lighthorizon/index/Makefile deleted file mode 100644 index 38361d7d37..0000000000 --- a/exp/lighthorizon/index/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -XDRS = xdr/LightHorizon-types.x - -XDRGEN_COMMIT=3f6808cd161d72474ffbe9eedbd7013de7f92748 - -.PHONY: xdr clean update - -xdr/xdr_generated.go: $(XDRS) - docker run -it --rm -v $$PWD:/wd -w /wd ruby /bin/bash -c '\ - gem install specific_install -v 0.3.7 && \ - gem specific_install https://github.com/stellar/xdrgen.git -b $(XDRGEN_COMMIT) && \ - xdrgen \ - --language go \ - --namespace xdr \ - --output xdr/ \ - $(XDRS)' - ls -lAh - go fmt $@ - -xdr: xdr/xdr_generated.go - -clean: - rm ./xdr/xdr_generated.go || true - -update: clean xdr diff --git a/exp/lighthorizon/index/backend/backend.go b/exp/lighthorizon/index/backend/backend.go deleted file mode 100644 index 580e5f4d6e..0000000000 --- a/exp/lighthorizon/index/backend/backend.go +++ /dev/null @@ -1,14 +0,0 @@ -package index - -import types "github.com/stellar/go/exp/lighthorizon/index/types" - -// TODO: Use a more standardized filesystem-style backend, so we can re-use -// code -type Backend interface { - Flush(map[string]types.NamedIndices) error - FlushAccounts([]string) error - Read(account string) (types.NamedIndices, error) - ReadAccounts() ([]string, error) - FlushTransactions(map[string]*types.TrieIndex) error - ReadTransactions(prefix string) (*types.TrieIndex, error) -} diff --git a/exp/lighthorizon/index/backend/file.go b/exp/lighthorizon/index/backend/file.go deleted file mode 100644 index 062b1efcdb..0000000000 --- a/exp/lighthorizon/index/backend/file.go +++ /dev/null @@ -1,214 +0,0 @@ -package index - -import ( - "bufio" - "compress/gzip" - "io" - "io/fs" - "os" - "path/filepath" - - types "github.com/stellar/go/exp/lighthorizon/index/types" - - "github.com/stellar/go/support/collections/set" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" -) - -type FileBackend struct { - dir string - parallel uint32 -} - -// NewFileBackend connects to indices stored at `dir`, creating the directory if one doesn't -// exist, and uses `parallel` to control how many workers to use when flushing to disk. -func NewFileBackend(dir string, parallel uint32) (*FileBackend, error) { - if parallel <= 0 { - parallel = 1 - } - - err := os.MkdirAll(dir, fs.ModeDir|0755) - if err != nil { - log.Errorf("Unable to mkdir %s, %v", dir, err) - return nil, err - } - - return &FileBackend{ - dir: dir, - parallel: parallel, - }, nil -} - -func (s *FileBackend) Flush(indexes map[string]types.NamedIndices) error { - return parallelFlush(s.parallel, indexes, s.writeBatch) -} - -func (s *FileBackend) FlushAccounts(accounts []string) error { - path := filepath.Join(s.dir, "accounts") - - f, err := os.OpenFile(path, os.O_CREATE| - os.O_APPEND| // crucial! since we might flush from various sources - os.O_WRONLY, - 0664) // rw-rw-r-- - - if err != nil { - return errors.Wrapf(err, "failed to open account file at %s", path) - } - - defer f.Close() - - // We write one account at a time because writes that occur within a single - // `write()` syscall are thread-safe. A larger write might be split into - // many calls and thus get interleaved, so we play it safe. - for _, account := range accounts { - f.Write([]byte(account + "\n")) - } - - return nil -} - -func (s *FileBackend) writeBatch(b *batch) error { - if len(b.indexes) == 0 { - return nil - } - - path := filepath.Join(s.dir, b.account[:3], b.account) - - err := os.MkdirAll(filepath.Dir(path), fs.ModeDir|0755) - if err != nil { - log.Errorf("Unable to mkdir %s, %v", filepath.Dir(path), err) - return nil - } - - f, err := os.Create(path) - if err != nil { - log.Errorf("Unable to create %s: %v", path, err) - return nil - } - defer f.Close() - - if _, err := writeGzippedTo(f, b.indexes); err != nil { - log.Errorf("Unable to serialize %s: %v", b.account, err) - return nil - } - - return nil -} - -func (s *FileBackend) FlushTransactions(indexes map[string]*types.TrieIndex) error { - // TODO: Parallelize this - for key, index := range indexes { - path := filepath.Join(s.dir, "tx", key) - - err := os.MkdirAll(filepath.Dir(path), fs.ModeDir|0755) - if err != nil { - log.Errorf("Unable to mkdir %s, %v", filepath.Dir(path), err) - continue - } - - f, err := os.Create(path) - if err != nil { - log.Errorf("Unable to create %s: %v", path, err) - continue - } - - zw := gzip.NewWriter(f) - if _, err := index.WriteTo(zw); err != nil { - log.Errorf("Unable to serialize %s: %v", path, err) - f.Close() - continue - } - - if err := zw.Close(); err != nil { - log.Errorf("Unable to serialize %s: %v", path, err) - f.Close() - continue - } - - if err := f.Close(); err != nil { - log.Errorf("Unable to save %s: %v", path, err) - } - } - return nil -} - -func (s *FileBackend) Read(account string) (types.NamedIndices, error) { - log.Debugf("Opening index: %s", account) - b, err := os.Open(filepath.Join(s.dir, account[:3], account)) - if err != nil { - return nil, err - } - defer b.Close() - - indexes, _, err := readGzippedFrom(bufio.NewReader(b)) - if err != nil { - log.Errorf("Unable to parse %s: %v", account, err) - return nil, os.ErrNotExist - } - return indexes, nil -} - -func (s *FileBackend) ReadAccounts() ([]string, error) { - path := filepath.Join(s.dir, "accounts") - log.Debugf("Opening accounts list at %s", path) - - f, err := os.Open(path) - if err != nil { - return nil, errors.Wrapf(err, "failed to open %s", path) - } - - const gAddressSize = 56 - - // We ballpark the capacity assuming all of the values being G-addresses. - preallocationSize := 100 * gAddressSize // default to 100 lines - info, err := os.Stat(path) - if err == nil { // we can still safely continue w/ errors - // Note that this will never be too large, but may be too small. - preallocationSize = int(info.Size()) / (gAddressSize + 1) // +1 for \n - } - accountMap := set.NewSet[string](preallocationSize) - accounts := make([]string, 0, preallocationSize) - - reader := bufio.NewReaderSize(f, 100*gAddressSize) // reasonable buffer size - for { - line, err := reader.ReadString(byte('\n')) - if err == io.EOF { - break - } else if err != nil { - return accounts, errors.Wrapf(err, "failed to read %s", path) - } - - account := line[:len(line)-1] // trim newline - - // The account list is very unlikely to be unique (especially if it was made - // w/ parallel flushes), so let's ensure that that's the case. - if !accountMap.Contains(account) { - accountMap.Add(account) - accounts = append(accounts, account) - } - } - - return accounts, nil -} - -func (s *FileBackend) ReadTransactions(prefix string) (*types.TrieIndex, error) { - log.Debugf("Opening index: %s", prefix) - b, err := os.Open(filepath.Join(s.dir, "tx", prefix)) - if err != nil { - return nil, err - } - defer b.Close() - zr, err := gzip.NewReader(b) - if err != nil { - log.Errorf("Unable to parse %s: %v", prefix, err) - return nil, os.ErrNotExist - } - defer zr.Close() - var index types.TrieIndex - _, err = index.ReadFrom(zr) - if err != nil { - log.Errorf("Unable to parse %s: %v", prefix, err) - return nil, os.ErrNotExist - } - return &index, nil -} diff --git a/exp/lighthorizon/index/backend/file_test.go b/exp/lighthorizon/index/backend/file_test.go deleted file mode 100644 index 6197f7b5c3..0000000000 --- a/exp/lighthorizon/index/backend/file_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package index - -import ( - "math/rand" - "testing" - - "github.com/stellar/go/keypair" - "github.com/stellar/go/xdr" - "github.com/stretchr/testify/require" -) - -func TestSimpleFileStore(t *testing.T) { - tmpDir := t.TempDir() - - // Create a large (beyond a single chunk) list of arbitrary accounts, some - // regular and some muxed. - accountList := make([]string, 123) - for i := range accountList { - var err error - var muxed xdr.MuxedAccount - address := keypair.MustRandom().Address() - - if rand.Intn(2) == 1 { - muxed, err = xdr.MuxedAccountFromAccountId(address, 12345678) - require.NoErrorf(t, err, "shouldn't happen") - } else { - muxed = xdr.MustMuxedAddress(address) - } - - accountList[i] = muxed.Address() - } - - require.Len(t, accountList, 123) - - file, err := NewFileBackend(tmpDir, 1) - require.NoError(t, err) - - require.NoError(t, file.FlushAccounts(accountList)) - - accounts, err := file.ReadAccounts() - require.NoError(t, err) - require.Equal(t, accountList, accounts) -} diff --git a/exp/lighthorizon/index/backend/gzip.go b/exp/lighthorizon/index/backend/gzip.go deleted file mode 100644 index 63c8e332c2..0000000000 --- a/exp/lighthorizon/index/backend/gzip.go +++ /dev/null @@ -1,74 +0,0 @@ -package index - -import ( - "bytes" - "compress/gzip" - "errors" - "io" - - types "github.com/stellar/go/exp/lighthorizon/index/types" -) - -func writeGzippedTo(w io.Writer, indexes types.NamedIndices) (int64, error) { - zw := gzip.NewWriter(w) - - var n int64 - for id, index := range indexes { - zw.Name = id - nWrote, err := io.Copy(zw, index.Buffer()) - n += nWrote - if err != nil { - return n, err - } - - if err := zw.Close(); err != nil { - return n, err - } - - zw.Reset(w) - } - - return n, nil -} - -func readGzippedFrom(r io.Reader) (types.NamedIndices, int64, error) { - if _, ok := r.(io.ByteReader); !ok { - return nil, 0, errors.New("reader *must* implement ByteReader") - } - - zr, err := gzip.NewReader(r) - if err != nil { - return nil, 0, err - } - - indexes := types.NamedIndices{} - var buf bytes.Buffer - var n int64 - for { - zr.Multistream(false) - - nRead, err := io.Copy(&buf, zr) - n += nRead - if err != nil { - return nil, n, err - } - - ind, err := types.NewBitmapIndex(buf.Bytes()) - if err != nil { - return nil, n, err - } - - indexes[zr.Name] = ind - - buf.Reset() - - err = zr.Reset(r) - if err == io.EOF { - break - } else if err != nil { - return nil, n, err - } - } - - return indexes, n, zr.Close() -} diff --git a/exp/lighthorizon/index/backend/gzip_test.go b/exp/lighthorizon/index/backend/gzip_test.go deleted file mode 100644 index 730e13185d..0000000000 --- a/exp/lighthorizon/index/backend/gzip_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package index - -import ( - "bufio" - "bytes" - "math/rand" - "os" - "path/filepath" - "testing" - - types "github.com/stellar/go/exp/lighthorizon/index/types" - "github.com/stretchr/testify/require" -) - -func TestGzipRoundtrip(t *testing.T) { - index := &types.BitmapIndex{} - anotherIndex := &types.BitmapIndex{} - for i := 0; i < 100+rand.Intn(1000); i++ { - index.SetActive(uint32(rand.Intn(10_000))) - anotherIndex.SetActive(uint32(rand.Intn(10_000))) - } - - indices := types.NamedIndices{ - "a": index, - "short/name": anotherIndex, - "slightlyLonger/name": index, - } - - var buf bytes.Buffer - wroteBytes, err := writeGzippedTo(&buf, indices) - require.NoError(t, err) - require.Greater(t, wroteBytes, int64(0)) - - gz := filepath.Join(t.TempDir(), "test.gzip") - require.NoError(t, os.WriteFile(gz, buf.Bytes(), 0644)) - f, err := os.Open(gz) - require.NoError(t, err) - defer f.Close() - - // Ensure that reading directly from a file errors out. - _, _, err = readGzippedFrom(f) - require.Error(t, err) - - read, readBytes, err := readGzippedFrom(bufio.NewReader(f)) - require.NoError(t, err) - require.Greater(t, readBytes, int64(0)) - - require.Equal(t, indices, read) - require.Equal(t, wroteBytes, readBytes) - require.Len(t, read, len(indices)) - - for name, index := range indices { - raw1, err := index.ToXDR().MarshalBinary() - require.NoError(t, err) - - raw2, err := read[name].ToXDR().MarshalBinary() - require.NoError(t, err) - - require.Equal(t, raw1, raw2) - } -} diff --git a/exp/lighthorizon/index/backend/parallel_flush.go b/exp/lighthorizon/index/backend/parallel_flush.go deleted file mode 100644 index 6f65bedc42..0000000000 --- a/exp/lighthorizon/index/backend/parallel_flush.go +++ /dev/null @@ -1,73 +0,0 @@ -package index - -import ( - "sync" - "sync/atomic" - "time" - - types "github.com/stellar/go/exp/lighthorizon/index/types" - "github.com/stellar/go/support/log" -) - -type batch struct { - account string - indexes types.NamedIndices -} - -type flushBatch func(b *batch) error - -func parallelFlush(parallel uint32, allIndexes map[string]types.NamedIndices, f flushBatch) error { - var wg sync.WaitGroup - - batches := make(chan *batch, parallel) - - wg.Add(1) - go func() { - // forces this async func to be waited on also, otherwise the outer - // method returns before this finishes. - defer wg.Done() - - for account, indexes := range allIndexes { - batches <- &batch{ - account: account, - indexes: indexes, - } - } - - if len(allIndexes) == 0 { - close(batches) - } - }() - - written := uint64(0) - for i := uint32(0); i < parallel; i++ { - wg.Add(1) - go func(workerNum uint32) { - defer wg.Done() - for batch := range batches { - if err := f(batch); err != nil { - log.Errorf("Error occurred writing batch: %v, retrying...", err) - time.Sleep(50 * time.Millisecond) - batches <- batch - continue - } - - nwritten := atomic.AddUint64(&written, 1) - if nwritten%1234 == 0 { - log.WithField("worker", workerNum). - Infof("Writing indices... %d/%d (%.2f%%)", - nwritten, len(allIndexes), - (float64(nwritten)/float64(len(allIndexes)))*100) - } - - if nwritten == uint64(len(allIndexes)) { - close(batches) - } - } - }(i) - } - - wg.Wait() - - return nil -} diff --git a/exp/lighthorizon/index/backend/s3.go b/exp/lighthorizon/index/backend/s3.go deleted file mode 100644 index a4f5a7e751..0000000000 --- a/exp/lighthorizon/index/backend/s3.go +++ /dev/null @@ -1,220 +0,0 @@ -package index - -import ( - "bytes" - "compress/gzip" - "os" - "path/filepath" - "strings" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/aws/aws-sdk-go/service/s3/s3manager" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" - - types "github.com/stellar/go/exp/lighthorizon/index/types" -) - -type S3Backend struct { - s3Session *session.Session - downloader *s3manager.Downloader - uploader *s3manager.Uploader - parallel uint32 - pathPrefix string - bucket string -} - -func NewS3Backend(awsConfig *aws.Config, bucket string, pathPrefix string, parallel uint32) (*S3Backend, error) { - s3Session, err := session.NewSession(awsConfig) - if err != nil { - return nil, err - } - - return &S3Backend{ - s3Session: s3Session, - downloader: s3manager.NewDownloader(s3Session), - uploader: s3manager.NewUploader(s3Session), - parallel: parallel, - pathPrefix: pathPrefix, - bucket: bucket, - }, nil -} - -func (s *S3Backend) FlushAccounts(accounts []string) error { - var buf bytes.Buffer - accountsString := strings.Join(accounts, "\n") - _, err := buf.WriteString(accountsString) - if err != nil { - return err - } - - path := filepath.Join(s.pathPrefix, "accounts") - - _, err = s.uploader.Upload(&s3manager.UploadInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - Body: &buf, - }) - if err != nil { - return err - } - - return nil -} - -func (s *S3Backend) Flush(indexes map[string]types.NamedIndices) error { - return parallelFlush(s.parallel, indexes, s.writeBatch) -} - -func (s *S3Backend) writeBatch(b *batch) error { - // TODO: re-use buffers in a pool - var buf bytes.Buffer - if _, err := writeGzippedTo(&buf, b.indexes); err != nil { - // TODO: Should we retry or what here?? - return errors.Wrapf(err, "unable to serialize %s", b.account) - } - - path := s.path(b.account) - - _, err := s.uploader.Upload(&s3manager.UploadInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - Body: &buf, - }) - if err != nil { - return errors.Wrapf(err, "unable to upload %s", b.account) - } - - return nil -} - -func (s *S3Backend) FlushTransactions(indexes map[string]*types.TrieIndex) error { - // TODO: Parallelize this - var buf bytes.Buffer - for key, index := range indexes { - buf.Reset() - path := filepath.Join(s.pathPrefix, "tx", key) - - zw := gzip.NewWriter(&buf) - if _, err := index.WriteTo(zw); err != nil { - log.Errorf("Unable to serialize %s: %v", path, err) - continue - } - - if err := zw.Close(); err != nil { - log.Errorf("Unable to serialize %s: %v", path, err) - continue - } - - _, err := s.uploader.Upload(&s3manager.UploadInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - Body: &buf, - }) - if err != nil { - log.Errorf("Unable to upload %s: %v", path, err) - // TODO: retries - continue - } - } - return nil -} - -func (s *S3Backend) ReadAccounts() ([]string, error) { - log.Debugf("Downloading accounts list") - b := &aws.WriteAtBuffer{} - path := filepath.Join(s.pathPrefix, "accounts") - n, err := s.downloader.Download(b, &s3.GetObjectInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - }) - if err != nil { - if aerr, ok := err.(awserr.Error); ok && aerr.Code() == s3.ErrCodeNoSuchKey { - return nil, os.ErrNotExist - } - return nil, errors.Wrapf(err, "Unable to download accounts list") - } - if n == 0 { - return nil, os.ErrNotExist - } - body := b.Bytes() - accounts := strings.Split(string(body), "\n") - return accounts, nil -} - -func (s *S3Backend) path(account string) string { - return filepath.Join(s.pathPrefix, account[:10], account) -} - -func (s *S3Backend) Read(account string) (types.NamedIndices, error) { - // Check if index exists in S3 - log.Debugf("Downloading index: %s", account) - var err error - for i := 0; i < 10; i++ { - b := &aws.WriteAtBuffer{} - path := s.path(account) - var n int64 - n, err = s.downloader.Download(b, &s3.GetObjectInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - }) - if err != nil { - if aerr, ok := err.(awserr.Error); ok && aerr.Code() == s3.ErrCodeNoSuchKey { - return nil, os.ErrNotExist - } - err = errors.Wrapf(err, "Unable to download %s", account) - time.Sleep(100 * time.Millisecond) - continue - } - if n == 0 { - return nil, os.ErrNotExist - } - var indexes map[string]*types.BitmapIndex - indexes, _, err = readGzippedFrom(bytes.NewReader(b.Bytes())) - if err != nil { - log.Errorf("Unable to parse %s: %v", account, err) - return nil, os.ErrNotExist - } - return indexes, nil - } - - return nil, err -} - -func (s *S3Backend) ReadTransactions(prefix string) (*types.TrieIndex, error) { - // Check if index exists in S3 - log.Debugf("Downloading index: %s", prefix) - b := &aws.WriteAtBuffer{} - path := filepath.Join(s.pathPrefix, "tx", prefix) - n, err := s.downloader.Download(b, &s3.GetObjectInput{ - Bucket: aws.String(s.bucket), - Key: aws.String(path), - }) - if err != nil { - if aerr, ok := err.(awserr.Error); ok && aerr.Code() == s3.ErrCodeNoSuchKey { - return nil, os.ErrNotExist - } - return nil, errors.Wrapf(err, "Unable to download %s", prefix) - } - if n == 0 { - return nil, os.ErrNotExist - } - zr, err := gzip.NewReader(bytes.NewReader(b.Bytes())) - if err != nil { - log.Errorf("Unable to parse %s: %v", prefix, err) - return nil, os.ErrNotExist - } - defer zr.Close() - - var index types.TrieIndex - _, err = index.ReadFrom(zr) - if err != nil { - log.Errorf("Unable to parse %s: %v", prefix, err) - return nil, os.ErrNotExist - } - return &index, nil -} diff --git a/exp/lighthorizon/index/builder.go b/exp/lighthorizon/index/builder.go deleted file mode 100644 index 324783b4f0..0000000000 --- a/exp/lighthorizon/index/builder.go +++ /dev/null @@ -1,366 +0,0 @@ -package index - -import ( - "context" - "fmt" - "io" - "math" - "os" - "sync" - "sync/atomic" - "time" - - "golang.org/x/sync/errgroup" - - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/ingest" - "github.com/stellar/go/ingest/ledgerbackend" - "github.com/stellar/go/metaarchive" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" - "github.com/stellar/go/support/storage" - "github.com/stellar/go/xdr" -) - -func BuildIndices( - ctx context.Context, - sourceUrl string, // where is raw txmeta coming from? - targetUrl string, // where should the resulting indices go? - networkPassphrase string, - ledgerRange historyarchive.Range, // inclusive - modules []string, - workerCount int, -) (*IndexBuilder, error) { - L := log.Ctx(ctx).WithField("service", "builder") - - indexStore, err := ConnectWithConfig(StoreConfig{ - URL: targetUrl, - Workers: uint32(workerCount), - Log: L.WithField("subservice", "index"), - }) - if err != nil { - return nil, err - } - - // We use historyarchive as a backend here just to abstract away dealing - // with the filesystem directly. - source, err := historyarchive.ConnectBackend( - sourceUrl, - storage.ConnectOptions{ - Context: ctx, - S3Region: "us-east-1", - }, - ) - if err != nil { - return nil, err - } - - metaArchive := metaarchive.NewMetaArchive(source) - - ledgerBackend := ledgerbackend.NewHistoryArchiveBackend(metaArchive) - - if ledgerRange.High == 0 { - var backendErr error - ledgerRange.High, backendErr = ledgerBackend.GetLatestLedgerSequence(ctx) - if backendErr != nil { - return nil, backendErr - } - } - - if ledgerRange.High < ledgerRange.Low { - return nil, fmt.Errorf("invalid ledger range: %s", ledgerRange.String()) - } - - ledgerCount := 1 + (ledgerRange.High - ledgerRange.Low) // +1 bc inclusive - parallel := int(max(1, uint32(workerCount))) - - startTime := time.Now() - L.Infof("Creating indices for ledger range: [%d, %d] (%d ledgers)", - ledgerRange.Low, ledgerRange.High, ledgerCount) - L.Infof("Using %d workers", parallel) - - // Create a bunch of workers that process ledgers a checkpoint range at a - // time (better than a ledger at a time to minimize flushes). - wg, ctx := errgroup.WithContext(ctx) - ch := make(chan historyarchive.Range, parallel) - - indexBuilder := NewIndexBuilder(indexStore, metaArchive, networkPassphrase) - for _, part := range modules { - switch part { - case "transactions": - indexBuilder.RegisterModule(ProcessTransaction) - case "accounts": - indexBuilder.RegisterModule(ProcessAccountsByCheckpoint) - case "accounts_by_ledger": - indexBuilder.RegisterModule(ProcessAccountsByLedger) - case "accounts_unbacked": - indexBuilder.RegisterModule(ProcessAccountsByCheckpointWithoutBackend) - indexStore.ClearMemory(false) - case "accounts_by_ledger_unbacked": - indexBuilder.RegisterModule(ProcessAccountsByLedgerWithoutBackend) - indexStore.ClearMemory(false) - default: - return indexBuilder, fmt.Errorf("unknown module '%s'", part) - } - } - - // Submit the work to the channels, breaking up the range into individual - // checkpoint ranges. - checkpoints := historyarchive.NewCheckpointManager(0) - go func() { - for ledger := range ledgerRange.GenerateCheckpoints(checkpoints) { - chunk := checkpoints.GetCheckpointRange(ledger) - chunk.High = min(chunk.High, ledgerRange.High) // don't exceed upper bound - chunk.Low = max(chunk.Low, ledgerRange.Low) // nor the lower bound - - ch <- chunk - } - - close(ch) - }() - - processed := uint64(0) - for i := 0; i < parallel; i++ { - wg.Go(func() error { - for ledgerRange := range ch { - count := (ledgerRange.High - ledgerRange.Low) + 1 - L.Debugf("Working on checkpoint range [%d, %d] (%d ledgers)", - ledgerRange.Low, ledgerRange.High, count) - - if err := indexBuilder.Build(ctx, ledgerRange); err != nil { - return errors.Wrapf(err, - "building indices for ledger range [%d, %d] failed", - ledgerRange.Low, ledgerRange.High) - } - - nprocessed := atomic.AddUint64(&processed, uint64(count)) - if nprocessed%1234 == 0 { - PrintProgress("Reading ledgers", nprocessed, uint64(ledgerCount), startTime) - } - - // Upload indices once every 10 checkpoints to save memory - if nprocessed%(10*uint64(checkpoints.GetCheckpointFrequency())) == 0 { - if err := indexStore.Flush(); err != nil { - return errors.Wrap(err, "flushing indices failed") - } - } - } - return nil - }) - } - - if err := wg.Wait(); err != nil { - return indexBuilder, errors.Wrap(err, "one or more workers failed") - } - - PrintProgress("Reading ledgers", processed, uint64(ledgerCount), startTime) - - L.Infof("Processed %d ledgers via %d workers", processed, parallel) - L.Infof("Uploading indices to %s", targetUrl) - if err := indexStore.Flush(); err != nil { - return indexBuilder, errors.Wrap(err, "flushing indices failed") - } - - // Assertion for testing - if processed != uint64(ledgerCount) { - L.Warnf("processed %d but expected %d", processed, ledgerCount) - } - - return indexBuilder, nil -} - -// Module is a way to process ingested data and shove it into an index store. -type Module func( - indexStore Store, - ledger xdr.LedgerCloseMeta, - transaction ingest.LedgerTransaction, -) error - -// IndexBuilder contains everything needed to build indices from ledger ranges. -type IndexBuilder struct { - store Store - metaArchive metaarchive.MetaArchive - networkPassphrase string - - lastBuiltLedgerWriteLock sync.Mutex - lastBuiltLedger uint32 - - modules []Module -} - -func NewIndexBuilder( - indexStore Store, - metaArchive metaarchive.MetaArchive, - networkPassphrase string, -) *IndexBuilder { - return &IndexBuilder{ - store: indexStore, - metaArchive: metaArchive, - networkPassphrase: networkPassphrase, - } -} - -// RegisterModule adds a module to process every given ledger. It is not -// threadsafe and all calls should be made *before* any calls to `Build`. -func (builder *IndexBuilder) RegisterModule(module Module) { - builder.modules = append(builder.modules, module) -} - -// RunModules executes all of the registered modules on the given ledger. -func (builder *IndexBuilder) RunModules( - ledger xdr.LedgerCloseMeta, - tx ingest.LedgerTransaction, -) error { - for _, module := range builder.modules { - if err := module(builder.store, ledger, tx); err != nil { - return err - } - } - - return nil -} - -// Build sequentially creates indices for each ledger in the given range based -// on the registered modules. -// -// TODO: We can probably optimize this by doing GetLedger in parallel with the -// ingestion & index building, since the network will be idle during the latter -// portion. -func (builder *IndexBuilder) Build(ctx context.Context, ledgerRange historyarchive.Range) error { - for ledgerSeq := ledgerRange.Low; ledgerSeq <= ledgerRange.High; ledgerSeq++ { - ledger, err := builder.metaArchive.GetLedger(ctx, ledgerSeq) - if err != nil { - if !os.IsNotExist(err) { - log.Errorf("error getting ledger %d: %v", ledgerSeq, err) - } - return err - } - - reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta( - builder.networkPassphrase, *ledger.V0) - if err != nil { - return err - } - - for { - tx, err := reader.Read() - if err == io.EOF { - break - } else if err != nil { - return err - } - - if err := builder.RunModules(*ledger.V0, tx); err != nil { - return err - } - } - } - - builder.lastBuiltLedgerWriteLock.Lock() - defer builder.lastBuiltLedgerWriteLock.Unlock() - builder.lastBuiltLedger = max(builder.lastBuiltLedger, ledgerRange.High) - - return nil -} - -func (builder *IndexBuilder) Watch(ctx context.Context) error { - latestLedger, err := builder.metaArchive.GetLatestLedgerSequence(ctx) - if err != nil { - log.Errorf("Failed to retrieve latest ledger: %v", err) - return err - } - nextLedger := builder.lastBuiltLedger + 1 - - log.Infof("Catching up to latest ledger: (%d, %d]", nextLedger, latestLedger) - if err = builder.Build(ctx, historyarchive.Range{ - Low: nextLedger, - High: latestLedger, - }); err != nil { - log.Errorf("Initial catchup failed: %v", err) - } - - for { - nextLedger = builder.lastBuiltLedger + 1 - log.Infof("Awaiting next ledger (%d)", nextLedger) - - // To keep the MVP simple, let's just naively poll the backend until the - // ledger we want becomes available. - // - // Refer to this thread [1] for a deeper brain dump on why we're - // preferring this over doing proper filesystem monitoring (e.g. - // fsnotify for on-disk). Essentially, supporting this for every - // possible index backend is a non-trivial amount of work with an - // uncertain payoff. - // - // [1]: https://stellarfoundation.slack.com/archives/C02B04RMK/p1654903342555669 - - // We sleep with linear backoff starting with 6s. Ledgers get posted - // every 5-7s on average, but to be extra careful, let's give it a full - // minute before we give up entirely. - timedCtx, cancel := context.WithTimeout(ctx, 60*time.Second) - defer cancel() - - sleepTime := (6 * time.Second) - outer: - for { - time.Sleep(sleepTime) - select { - case <-timedCtx.Done(): - return errors.Wrap(timedCtx.Err(), "awaiting next ledger failed") - - default: - buildErr := builder.Build(timedCtx, historyarchive.Range{ - Low: nextLedger, - High: nextLedger, - }) - if buildErr == nil { - break outer - } - - if os.IsNotExist(buildErr) { - sleepTime += (time.Second * 2) - continue - } - - return errors.Wrap(buildErr, "awaiting next ledger failed") - } - } - } -} - -func PrintProgress(prefix string, done, total uint64, startTime time.Time) { - progress := float64(done) / float64(total) - elapsed := time.Since(startTime) - - // Approximate based on how many stuff is left to do and how long this much - // progress took, e.g. if 4/10 took 2s then 6/10 will "take" 3s (though this - // assumes consistent load). - remaining := (float64(elapsed) / float64(done)) * float64(total-done) - - var remainingStr string - if math.IsInf(remaining, 0) || math.IsNaN(remaining) { - remainingStr = "unknown" - } else { - remainingStr = time.Duration(remaining).Round(time.Millisecond).String() - } - - log.Infof("%s - %.1f%% (%d/%d) - elapsed: %s, remaining: ~%s", prefix, - 100*progress, done, total, - elapsed.Round(time.Millisecond), - remainingStr, - ) -} - -func min(a, b uint32) uint32 { - if a < b { - return a - } - return b -} - -func max(a, b uint32) uint32 { - if a > b { - return a - } - return b -} diff --git a/exp/lighthorizon/index/cmd/batch/doc.go b/exp/lighthorizon/index/cmd/batch/doc.go deleted file mode 100644 index 70e55009d5..0000000000 --- a/exp/lighthorizon/index/cmd/batch/doc.go +++ /dev/null @@ -1,52 +0,0 @@ -// Package batch provides two commands: map and reduce that can be run in AWS -// Batch to generate indexes for occurences of accounts in each checkpoint. -// -// map step is using AWS_BATCH_JOB_ARRAY_INDEX env variable provided by AWS -// Batch to cut all checkpoint history into smaller chunks, each processed by a -// single map batch job (and by multiple parallel workers in a single job). A -// single job simply creates indexes for a given range of checkpoints and save -// indexes and all accounts seen in a given range (FlushAccounts method) to a -// job folder (job_X, X = 0, 1, 2, 3, ...) in S3. -// -// network history split into chunks: -// [ | | | | | | | | | | | | | | | | | | | | | ] -// ---- -// / \ -// / \ -// / \ -// [..........] <- each chunk consists of checkpoints -// | -// . - each checkpoint is processed by a free -// worker (go routine) -// -// reduce step is responsible for merging all indexes created in map step into a -// final indexes for each account and for entire network history. Each reduce -// job goes through all map job results (0..MAP_JOBS) and reads all accounts -// processed in a given map job. Then for each account it merges indexes from -// all map jobs. Each reduce job maintains `doneAccounts` map because if a given -// account index was processed earlier it should be skipped instead of being -// processed again. Each reduce job also runs multiple parallel workers. Finally -// the method that is used to determine if the following (job, worker) should -// process a given account is using a 64-bit hash of account ID. The hash is -// split into two 32-bit parts: left and right. If the left part modulo -// REDUCE_JOBS is equal the job index and the right part modulo a number of -// parallel workers is equal the worker index then the account is processed. -// Otherwise it's skipped (and will be picked by another (job, worker) pair). -// -// map step results saved in S3: -// x x x x x x x x x x x x x x x x x x x x x x x x x x x x -// | -// ㄴ job0/accounts <- each job results contains a list of accounts -// | processed by a given job... -// | -// ㄴ job0/... <- ...and partial indexes -// -// hash(account_id) => XXXX YYYY <- 64 bit hash of account id is calculated -// -// if XXXX % REDUCE_JOBS == JOB_ID and YYYY % WORKERS_COUNT = WORKER_ID -// then process a given account by merging all indexes of a given account -// in all map step results, then mark account as done so if the account -// is seen again it will be skiped, -// -// else: skip the account. -package batch diff --git a/exp/lighthorizon/index/cmd/batch/map/main.go b/exp/lighthorizon/index/cmd/batch/map/main.go deleted file mode 100644 index 384e99ee80..0000000000 --- a/exp/lighthorizon/index/cmd/batch/map/main.go +++ /dev/null @@ -1,144 +0,0 @@ -package main - -import ( - "context" - "fmt" - "os" - "runtime" - "strconv" - "strings" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/network" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" -) - -type BatchConfig struct { - historyarchive.Range - TxMetaSourceUrl string - IndexTargetUrl string - NetworkPassphrase string -} - -const ( - batchSizeEnv = "BATCH_SIZE" - jobIndexEnvName = "JOB_INDEX_ENV" - firstCheckpointEnv = "FIRST_CHECKPOINT" - txmetaSourceUrlEnv = "TXMETA_SOURCE" - indexTargetUrlEnv = "INDEX_TARGET" - workerCountEnv = "WORKER_COUNT" - networkPassphraseEnv = "NETWORK_PASSPHRASE" - modulesEnv = "MODULES" -) - -func NewBatchConfig() (*BatchConfig, error) { - indexTargetRootUrl := os.Getenv(indexTargetUrlEnv) - if indexTargetRootUrl == "" { - return nil, errors.New("required parameter: " + indexTargetUrlEnv) - } - - jobIndexEnv := os.Getenv(jobIndexEnvName) - if jobIndexEnv == "" { - return nil, errors.New("env variable can't be empty " + jobIndexEnvName) - } - jobIndex, err := strconv.ParseUint(os.Getenv(jobIndexEnv), 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+jobIndexEnv) - } - - firstCheckpoint, err := strconv.ParseUint(os.Getenv(firstCheckpointEnv), 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+firstCheckpointEnv) - } - - checkpoints := historyarchive.NewCheckpointManager(0) - if !checkpoints.IsCheckpoint(uint32(firstCheckpoint - 1)) { - return nil, fmt.Errorf( - "%s (%d) must be the first ledger in a checkpoint range", - firstCheckpointEnv, firstCheckpoint) - } - - batchSize, err := strconv.ParseUint(os.Getenv(batchSizeEnv), 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+batchSizeEnv) - } else if batchSize%uint64(checkpoints.GetCheckpointFrequency()) != 0 { - return nil, fmt.Errorf( - "%s (%d) must be a multiple of checkpoint frequency (%d)", - batchSizeEnv, batchSize, checkpoints.GetCheckpointFrequency()) - } - - txmetaSourceUrl := os.Getenv(txmetaSourceUrlEnv) - if txmetaSourceUrl == "" { - return nil, errors.New("required parameter " + txmetaSourceUrlEnv) - } - - firstLedger := uint32(firstCheckpoint + batchSize*jobIndex) - lastLedger := firstLedger + uint32(batchSize) - 1 - return &BatchConfig{ - Range: historyarchive.Range{Low: firstLedger, High: lastLedger}, - TxMetaSourceUrl: txmetaSourceUrl, - IndexTargetUrl: fmt.Sprintf("%s%cjob_%d", indexTargetRootUrl, os.PathSeparator, jobIndex), - }, nil -} - -func main() { - log.SetLevel(log.InfoLevel) - // log.SetLevel(log.DebugLevel) - - batch, err := NewBatchConfig() - if err != nil { - panic(err) - } - - var workerCount int - workerCountStr := os.Getenv(workerCountEnv) - if workerCountStr == "" { - workerCount = runtime.NumCPU() - } else { - workerCountParsed, innerErr := strconv.ParseUint(workerCountStr, 10, 8) - if innerErr != nil { - panic(errors.Wrapf(innerErr, - "invalid worker count parameter (%s)", workerCountStr)) - } - workerCount = int(workerCountParsed) - } - - networkPassphrase := os.Getenv(networkPassphraseEnv) - switch networkPassphrase { - case "": - log.Warnf("%s not specified, defaulting to 'testnet'", networkPassphraseEnv) - fallthrough - case "testnet": - networkPassphrase = network.TestNetworkPassphrase - case "pubnet": - networkPassphrase = network.PublicNetworkPassphrase - default: - log.Warnf("%s is not a recognized shortcut ('pubnet' or 'testnet')", - networkPassphraseEnv) - } - log.Infof("Using network passphrase '%s'", networkPassphrase) - - parsedModules := []string{} - if modules := os.Getenv(modulesEnv); modules == "" { - parsedModules = append(parsedModules, "accounts_unbacked") - } else { - parsedModules = append(parsedModules, strings.Split(modules, ",")...) - } - - log.Infof("Uploading ledger range [%d, %d] to %s", - batch.Range.Low, batch.Range.High, batch.IndexTargetUrl) - - if _, err := index.BuildIndices( - context.Background(), - batch.TxMetaSourceUrl, - batch.IndexTargetUrl, - networkPassphrase, - batch.Range, - parsedModules, - workerCount, - ); err != nil { - panic(err) - } -} diff --git a/exp/lighthorizon/index/cmd/batch/reduce/main.go b/exp/lighthorizon/index/cmd/batch/reduce/main.go deleted file mode 100644 index bff9f8216a..0000000000 --- a/exp/lighthorizon/index/cmd/batch/reduce/main.go +++ /dev/null @@ -1,389 +0,0 @@ -package main - -import ( - "encoding/hex" - "hash/fnv" - "os" - "strconv" - "strings" - "sync" - - "github.com/stellar/go/exp/lighthorizon/index" - types "github.com/stellar/go/exp/lighthorizon/index/types" - "github.com/stellar/go/support/collections/set" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" -) - -const ( - ACCOUNT_FLUSH_FREQUENCY = 200 - // arbitrary default, should we use runtime.NumCPU()? - DEFAULT_WORKER_COUNT = 2 -) - -type ReduceConfig struct { - JobIndex uint32 - MapJobCount uint32 - ReduceJobCount uint32 - IndexTarget string - IndexRootSource string - - Workers uint32 -} - -func ReduceConfigFromEnvironment() (*ReduceConfig, error) { - const ( - mapJobsEnv = "MAP_JOB_COUNT" - reduceJobsEnv = "REDUCE_JOB_COUNT" - workerCountEnv = "WORKER_COUNT" - jobIndexEnvName = "JOB_INDEX_ENV" - indexRootSourceEnv = "INDEX_SOURCE_ROOT" - indexTargetEnv = "INDEX_TARGET" - ) - - jobIndexEnv := strings.TrimSpace(os.Getenv(jobIndexEnvName)) - if jobIndexEnv == "" { - return nil, errors.New("env variable can't be empty " + jobIndexEnvName) - } - - jobIndex, err := strconv.ParseUint(strings.TrimSpace(os.Getenv(jobIndexEnv)), 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+jobIndexEnv) - } - mapJobCount, err := strconv.ParseUint(strings.TrimSpace(os.Getenv(mapJobsEnv)), 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+mapJobsEnv) - } - reduceJobCount, err := strconv.ParseUint(strings.TrimSpace(os.Getenv(reduceJobsEnv)), 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+reduceJobsEnv) - } - - workersStr := strings.TrimSpace(os.Getenv(workerCountEnv)) - if workersStr == "" { - workersStr = strconv.FormatUint(DEFAULT_WORKER_COUNT, 10) - } - workers, err := strconv.ParseUint(workersStr, 10, 32) - if err != nil { - return nil, errors.Wrap(err, "invalid parameter "+workerCountEnv) - } - - indexTarget := strings.TrimSpace(os.Getenv(indexTargetEnv)) - if indexTarget == "" { - return nil, errors.New("required parameter missing " + indexTargetEnv) - } - - indexRootSource := strings.TrimSpace(os.Getenv(indexRootSourceEnv)) - if indexRootSource == "" { - return nil, errors.New("required parameter missing " + indexRootSourceEnv) - } - - return &ReduceConfig{ - JobIndex: uint32(jobIndex), - MapJobCount: uint32(mapJobCount), - ReduceJobCount: uint32(reduceJobCount), - Workers: uint32(workers), - IndexTarget: indexTarget, - IndexRootSource: indexRootSource, - }, nil -} - -func main() { - log.SetLevel(log.InfoLevel) - - config, err := ReduceConfigFromEnvironment() - if err != nil { - panic(err) - } - - log.Infof("Connecting to %s", config.IndexTarget) - finalIndexStore, err := index.Connect(config.IndexTarget) - if err != nil { - panic(errors.Wrapf(err, "failed to connect to indices at %s", - config.IndexTarget)) - } - - if err := mergeAllIndices(finalIndexStore, config); err != nil { - panic(errors.Wrap(err, "failed to merge indices")) - } -} - -func mergeAllIndices(finalIndexStore index.Store, config *ReduceConfig) error { - doneAccounts := set.NewSafeSet[string](512) - for i := uint32(0); i < config.MapJobCount; i++ { - jobLogger := log.WithField("job", i) - - jobSubPath := "job_" + strconv.FormatUint(uint64(i), 10) - jobLogger.Infof("Connecting to url %s, sub-path %s", config.IndexRootSource, jobSubPath) - outerJobStore, err := index.ConnectWithConfig(index.StoreConfig{ - URL: config.IndexRootSource, - URLSubPath: jobSubPath, - }) - - if err != nil { - return errors.Wrapf(err, "failed to connect to indices at %s, sub-path %s", config.IndexRootSource, jobSubPath) - } - - accounts, err := outerJobStore.ReadAccounts() - // TODO: in final version this should be critical error, now just skip it - if os.IsNotExist(err) { - jobLogger.Errorf("accounts file not found (TODO!)") - continue - } else if err != nil { - return errors.Wrapf(err, "failed to read accounts for job %d", i) - } - - jobLogger.Infof("Processing %d accounts with %d workers", - len(accounts), config.Workers) - - workQueues := make([]chan string, config.Workers) - for i := range workQueues { - workQueues[i] = make(chan string, 1) - } - - for idx, queue := range workQueues { - go (func(index uint32, queue chan string) { - for _, account := range accounts { - // Account index already merged in the previous outer job? - if doneAccounts.Contains(account) { - continue - } - - // Account doesn't belong in this work queue? - if !config.shouldProcessAccount(account, index) { - continue - } - - queue <- account - } - - close(queue) - })(uint32(idx), queue) - } - - // TODO: errgroup.WithContext(ctx) - var wg sync.WaitGroup - wg.Add(int(config.Workers)) - for j := uint32(0); j < config.Workers; j++ { - go func(routineIndex uint32) { - defer wg.Done() - accountLog := jobLogger. - WithField("worker", routineIndex). - WithField("subservice", "accounts") - accountLog.Info("Started worker") - - var accountsProcessed, accountsSkipped uint64 - for account := range workQueues[routineIndex] { - accountLog. - WithField("total", len(accounts)). - WithField("indexed", accountsProcessed). - WithField("skipped", accountsSkipped) - - accountLog.Debugf("Account: %s", account) - if (accountsProcessed+accountsSkipped)%97 == 0 { - accountLog.Infof("Processed %d/%d accounts", - accountsProcessed+accountsSkipped, len(accounts)) - } - - accountLog.Debugf("Reading index for account: %s", account) - - // First, open the "final merged indices" at the root level - // for this account. - mergedIndices, readErr := outerJobStore.Read(account) - - // TODO: in final version this should be critical error, now just skip it - if os.IsNotExist(readErr) { - accountLog.Errorf("Account %s is unavailable - TODO fix", account) - continue - } else if err != nil { - panic(readErr) - } - - // Then, iterate through all of the job folders and merge - // indices from all jobs that touched this account. - for k := uint32(0); k < config.MapJobCount; k++ { - var jobErr error - - // FIXME: This could probably come from a pool. Every - // worker needs to have a connection to every index - // store, so there's no reason to re-open these for each - // inner loop. - innerJobSubPath := "job_" + strconv.FormatUint(uint64(k), 10) - innerJobStore, jobErr := index.ConnectWithConfig(index.StoreConfig{ - URL: config.IndexRootSource, - URLSubPath: innerJobSubPath, - }) - - if jobErr != nil { - accountLog.WithError(jobErr). - Errorf("Failed to open index at %s, sub-path %s", config.IndexRootSource, innerJobSubPath) - panic(jobErr) - } - - jobIndices, jobErr := innerJobStore.Read(account) - - // This job never touched this account; skip. - if os.IsNotExist(jobErr) { - continue - } else if jobErr != nil { - accountLog.WithError(jobErr). - Errorf("Failed to read index for %s", account) - panic(jobErr) - } - - if jobErr = mergeIndices(mergedIndices, jobIndices); jobErr != nil { - accountLog.WithError(jobErr). - Errorf("Merge failure for index at %s, sub-path %s", config.IndexRootSource, innerJobSubPath) - panic(jobErr) - } - } - - // Finally, save the merged index. - finalIndexStore.AddParticipantToIndexesNoBackend(account, mergedIndices) - - // Mark this account for other workers to ignore. - doneAccounts.Add(account) - accountsProcessed++ - accountLog = accountLog.WithField("processed", accountsProcessed) - - // Periodically flush to disk to save memory. - if accountsProcessed%ACCOUNT_FLUSH_FREQUENCY == 0 { - accountLog.Infof("Flushing indexed accounts.") - if flushErr := finalIndexStore.Flush(); flushErr != nil { - accountLog.WithError(flushErr).Errorf("Flush error.") - panic(flushErr) - } - } - } - - accountLog.Infof("Final account flush.") - if err = finalIndexStore.Flush(); err != nil { - accountLog.WithError(err).Errorf("Flush error.") - panic(err) - } - - // Merge the transaction indexes - // There's 256 files, (one for each first byte of the txn hash) - txLog := jobLogger. - WithField("worker", routineIndex). - WithField("subservice", "transactions") - - var prefixesProcessed, prefixesSkipped uint64 - for i := int(0x00); i <= 0xff; i++ { - b := byte(i) // can't loop over range bc overflow - if b%97 == 0 { - txLog.Infof("Processed %d/%d prefixes (%d skipped)", - prefixesProcessed, 0xff, prefixesSkipped) - } - - if !config.shouldProcessTx(b, routineIndex) { - prefixesSkipped++ - continue - } - - txLog = txLog. - WithField("indexed", prefixesProcessed). - WithField("skipped", prefixesSkipped) - - prefix := hex.EncodeToString([]byte{b}) - for k := uint32(0); k < config.MapJobCount; k++ { - var innerErr error - innerJobSubPath := "job_" + strconv.FormatUint(uint64(k), 10) - innerJobStore, innerErr := index.ConnectWithConfig(index.StoreConfig{ - URL: config.IndexRootSource, - URLSubPath: innerJobSubPath, - }) - - if innerErr != nil { - txLog.WithError(innerErr).Errorf("Failed to open index at %s, sub-path %s", config.IndexRootSource, innerJobSubPath) - panic(innerErr) - } - - innerTxnIndexes, innerErr := innerJobStore.ReadTransactions(prefix) - if os.IsNotExist(innerErr) { - continue - } else if innerErr != nil { - txLog.WithError(innerErr).Errorf("Error reading tx prefix %s", prefix) - panic(innerErr) - } - - if innerErr = finalIndexStore.MergeTransactions(prefix, innerTxnIndexes); innerErr != nil { - txLog.WithError(innerErr).Errorf("Error merging txs at prefix %s", prefix) - panic(innerErr) - } - } - - prefixesProcessed++ - } - - txLog = txLog. - WithField("indexed", prefixesProcessed). - WithField("skipped", prefixesSkipped) - - txLog.Infof("Final transaction flush...") - if err = finalIndexStore.Flush(); err != nil { - txLog.Errorf("Error flushing transactions: %v", err) - panic(err) - } - }(j) - } - - wg.Wait() - } - - return nil -} - -func (cfg *ReduceConfig) shouldProcessAccount(account string, routineIndex uint32) bool { - hash := fnv.New64a() - - // Docs state (https://pkg.go.dev/hash#Hash) that Write will never error. - hash.Write([]byte(account)) - digest := uint32(hash.Sum64()) // discard top 32 bits - - leftHalf := digest >> 16 - rightHalf := digest & 0x0000FFFF - - log.WithField("worker", routineIndex). - WithField("account", account). - Debugf("Hash: %d (left=%d, right=%d)", digest, leftHalf, rightHalf) - - // Because the digest is basically a random number (given a good hash - // function), its remainders w.r.t. the indices will distribute the work - // fairly (and deterministically). - return leftHalf%cfg.ReduceJobCount == cfg.JobIndex && - rightHalf%cfg.Workers == routineIndex -} - -func (cfg *ReduceConfig) shouldProcessTx(txPrefix byte, routineIndex uint32) bool { - hashLeft := uint32(txPrefix >> 4) - hashRight := uint32(txPrefix & 0x0F) - - // Because the transaction hash (and thus the first byte or "prefix") is a - // random value, its remainders w.r.t. the indices will distribute the work - // fairly (and deterministically). - return hashRight%cfg.ReduceJobCount == cfg.JobIndex && - hashLeft%cfg.Workers == routineIndex -} - -// For every index that exists in `dest`, finds the corresponding index in -// `source` and merges it into `dest`'s version. -func mergeIndices(dest, source map[string]*types.BitmapIndex) error { - for name, index := range dest { - // The source doesn't contain this particular index. - // - // This probably shouldn't happen, since during the Map step, there's no - // way to choose which indices you want, but, strictly-speaking, it's - // not an error, so we can just move on. - innerIndices, ok := source[name] - if !ok || innerIndices == nil { - continue - } - - if err := index.Merge(innerIndices); err != nil { - return errors.Wrapf(err, "failed to merge index for %s", name) - } - } - - return nil -} diff --git a/exp/lighthorizon/index/cmd/map.sh b/exp/lighthorizon/index/cmd/map.sh deleted file mode 100755 index 390370f2cb..0000000000 --- a/exp/lighthorizon/index/cmd/map.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/bash -# -# Breaks up the given ledger dumps into checkpoints and runs a map -# job on each one. However, it's the Golang side does validation that -# the map job resulted in the correct indices. -# - -# check parameters and their validity (types, existence, etc.) - -if [[ "$#" -ne "2" ]]; then - echo "Usage: $0 " - exit 1 -fi - -if [[ ! -d "$1" ]]; then - echo "Error: txmeta src ('$1') does not exist" - echo "Usage: $0 " - exit 1 -fi - -if [[ -z $BATCH_SIZE ]]; then - echo "BATCH_SIZE environmental variable required" - exit 1 -elif ! [[ $BATCH_SIZE =~ ^[0-9]+$ ]]; then - echo "BATCH_SIZE ('$BATCH_SIZE') must be an integer" - exit 1 -fi - -if [[ -z $FIRST_LEDGER || -z $LAST_LEDGER ]]; then - echo "FIRST_LEDGER and LAST_LEDGER environmental variables required" - exit 1 -elif ! [[ $FIRST_LEDGER =~ ^[0-9]+$ && $LAST_LEDGER =~ ^[0-9]+$ ]]; then - echo "FIRST_LEDGER ('$FIRST_LEDGER') and LAST_LEDGER ('$LAST_LEDGER') must be integers" - exit 1 -fi - -if [[ ! -d "$2" ]]; then - echo "Warning: index dest ('$2') does not exist, creating..." - mkdir -p $2 -fi - -# do work - -FIRST=$FIRST_LEDGER -LAST=$LAST_LEDGER -COUNT=$(($LAST-$FIRST+1)) -# batches = ceil(count / batch_size) -# formula is from https://stackoverflow.com/a/12536521 -BATCH_COUNT=$(( ($COUNT + $BATCH_SIZE - 1) / $BATCH_SIZE )) - -if [[ "$(((LAST + 1) % 64))" -ne "0" ]]; then - echo "LAST_LEDGER ($LAST_LEDGER) should be a checkpoint ledger" - exit 1 -fi - -echo " - start: $FIRST" -echo " - end: $LAST" -echo " - count: $COUNT ($BATCH_COUNT batches @ $BATCH_SIZE ledgers each)" - -go build -o ./map ./batch/map/... -if [[ "$?" -ne "0" ]]; then - echo "Build failed" - exit 1 -fi - -pids=( ) -for (( i=0; i < $BATCH_COUNT; i++ )) -do - echo -n "Creating map job $i... " - - NETWORK_PASSPHRASE='testnet' JOB_INDEX_ENV='AWS_BATCH_JOB_ARRAY_INDEX' MODULES='accounts_unbacked,transactions' \ - AWS_BATCH_JOB_ARRAY_INDEX=$i BATCH_SIZE=$BATCH_SIZE FIRST_CHECKPOINT=$FIRST \ - TXMETA_SOURCE=file://$1 INDEX_TARGET=file://$2 WORKER_COUNT=1 \ - ./map & - - echo "pid=$!" - pids+=($!) -done - -sleep $BATCH_COUNT - -# Check the status codes for all of the map processes. -for i in "${!pids[@]}"; do - pid=${pids[$i]} - echo -n "Checking job $i (pid=$pid)... " - if ! wait "$pid"; then - echo "failed" - exit 1 - else - echo "succeeded!" - fi -done - -rm ./map -echo "All jobs succeeded!" -exit 0 diff --git a/exp/lighthorizon/index/cmd/mapreduce_test.go b/exp/lighthorizon/index/cmd/mapreduce_test.go deleted file mode 100644 index db529fd8bc..0000000000 --- a/exp/lighthorizon/index/cmd/mapreduce_test.go +++ /dev/null @@ -1,232 +0,0 @@ -package main_test - -import ( - "encoding/hex" - "fmt" - "io" - "net/url" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - "testing" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/network" - "github.com/stellar/go/support/collections/maps" - "github.com/stellar/go/support/collections/set" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -const ( - batchSize = 128 -) - -func TestMap(t *testing.T) { - RunMapTest(t) -} - -func TestReduce(t *testing.T) { - // First, map the index files like we normally would. - startLedger, endLedger, jobRoot := RunMapTest(t) - batchCount := (endLedger - startLedger + batchSize) / batchSize // ceil(ledgerCount / batchSize) - - // Now that indices have been "map"ped, reduce them to a single store. - - indexTarget := filepath.Join(t.TempDir(), "final-indices") - reduceTestCmd := exec.Command("./reduce.sh", jobRoot, indexTarget) - t.Logf("Running %d reduce jobs: %s", batchCount, reduceTestCmd.String()) - stdout, err := reduceTestCmd.CombinedOutput() - t.Logf(string(stdout)) - require.NoError(t, err) - - // Then, build the *same* indices using the single-process tester. - - t.Logf("Building baseline for ledger range [%d, %d]", startLedger, endLedger) - hashes, participants := IndexLedgerRange(t, txmetaSource, startLedger, endLedger) - - // Finally, compare the two to make sure the reduce job did what it's - // supposed to do. - - indexStore, err := index.Connect("file://" + indexTarget) - require.NoError(t, err) - stores := []index.Store{indexStore} // to reuse code: same as array of 1 store - - assertParticipantsEqual(t, maps.Keys(participants), stores) - for account, checkpoints := range participants { - assertParticipantCheckpointsEqual(t, account, checkpoints, stores) - } - - assertTOIDsEqual(t, hashes, stores) -} - -func RunMapTest(t *testing.T) (uint32, uint32, string) { - // Only file:// style URLs for the txmeta source are allowed while testing. - parsed, err := url.Parse(txmetaSource) - require.NoErrorf(t, err, "%s is not a valid URL", txmetaSource) - if parsed.Scheme != "file" { - t.Logf("%s is not local txmeta source", txmetaSource) - t.Skip() - } - txmetaPath := strings.Replace(txmetaSource, "file://", "", 1) - - // What ledger range are we working with? - checkpointMgr := historyarchive.NewCheckpointManager(0) - startLedger, endLedger := GetFixtureLedgerRange(t) - - // The map job *requires* that each one operate on a multiple of a - // checkpoint range, so we may need to adjust the ranges (depending on how - // many ledgers are in the fixutre) and break them up accordingly. - if !checkpointMgr.IsCheckpoint(startLedger - 1) { - startLedger = checkpointMgr.NextCheckpoint(startLedger-1) + 1 - } - if (endLedger-startLedger)%batchSize != 0 { - endLedger = checkpointMgr.PrevCheckpoint((endLedger / batchSize) * batchSize) - } - - require.Greaterf(t, endLedger, startLedger, - "not enough fixtures for batchSize=%d", batchSize) - - batchCount := (endLedger - startLedger + batchSize) / batchSize // ceil(ledgerCount / batchSize) - - t.Logf("Using %d batches to process ledger range [%d, %d]", - batchCount, startLedger, endLedger) - - require.Truef(t, - batchCount == 1 || checkpointMgr.IsCheckpoint(startLedger+batchSize-1), - "expected batch size (%d) to result in checkpoint blocks, "+ - "but start+batchSize+1 (%d+%d+1=%d) is not a checkpoint", - batchSize, batchSize, startLedger, batchSize+startLedger+1) - - // First, execute the map jobs in parallel and dump the resulting indices to - // a temporary directory. - - tempDir := filepath.Join(t.TempDir(), "indices-map") - mapTestCmd := exec.Command("./map.sh", txmetaPath, tempDir) - mapTestCmd.Env = append(os.Environ(), - fmt.Sprintf("BATCH_SIZE=%d", batchSize), - fmt.Sprintf("FIRST_LEDGER=%d", startLedger), - fmt.Sprintf("LAST_LEDGER=%d", endLedger), - fmt.Sprintf("NETWORK_PASSPHRASE='%s'", network.TestNetworkPassphrase)) - t.Logf("Running %d map jobs: %s", batchCount, mapTestCmd.String()) - stdout, err := mapTestCmd.CombinedOutput() - - t.Logf("Tried writing indices to %s:", tempDir) - t.Log(string(stdout)) - require.NoError(t, err) - - // Then, build the *same* indices using the single-process tester. - t.Logf("Building baseline for ledger range [%d, %d]", startLedger, endLedger) - hashes, participants := IndexLedgerRange(t, txmetaSource, startLedger, endLedger) - - // Now, walk through the mapped indices and ensure that at least one of the - // jobs reported the same indices for tx TOIDs and participation. - - stores := make([]index.Store, batchCount) - for i := range stores { - indexUrl := filepath.Join( - "file://", - tempDir, - "job_"+strconv.FormatUint(uint64(i), 10), - ) - index, err := index.Connect(indexUrl) - require.NoError(t, err) - require.NotNil(t, index) - stores[i] = index - - t.Logf("Connected to index #%d at %s", i+1, indexUrl) - } - - assertParticipantsEqual(t, maps.Keys(participants), stores) - for account, checkpoints := range participants { - assertParticipantCheckpointsEqual(t, account, checkpoints, stores) - } - - assertTOIDsEqual(t, hashes, stores) - - return startLedger, endLedger, tempDir -} - -func assertParticipantsEqual(t *testing.T, - expectedAccountSet []string, - indexGroup []index.Store, -) { - indexGroupAccountSet := set.NewSet[string](len(expectedAccountSet)) - for _, store := range indexGroup { - accounts, err := store.ReadAccounts() - require.NoError(t, err) - indexGroupAccountSet.AddSlice(accounts) - } - - assert.Lenf(t, indexGroupAccountSet, len(expectedAccountSet), - "quantity of accounts across indices doesn't match") - - mappedAccountSet := maps.Keys(indexGroupAccountSet) - require.ElementsMatch(t, expectedAccountSet, mappedAccountSet) -} - -func assertParticipantCheckpointsEqual(t *testing.T, - account string, - expected []uint32, - indexGroup []index.Store, -) { - // Ensure that all of the active checkpoints reported by the index match - // the ones we tracked while ingesting the range ourselves. - - foundCheckpoints := set.NewSet[uint32](len(expected)) - for _, store := range indexGroup { - var err error - var lastActiveCheckpoint uint32 = 0 - for { - lastActiveCheckpoint, err = store.NextActive(account, "all/all", lastActiveCheckpoint) - if err == io.EOF { - break - } - require.NoError(t, err) // still an error since it shouldn't happen - - foundCheckpoints.Add(lastActiveCheckpoint) - lastActiveCheckpoint += 1 // hit next active one - } - } - - // Error out if there were any extraneous checkpoints found. - for chk := range foundCheckpoints { - require.Containsf(t, expected, chk, - "found unexpected checkpoint %d", int(chk)) - } - - // Make sure everything got marked as expected in at least one index. - for _, item := range expected { - require.Containsf(t, foundCheckpoints, item, - "failed to find %d for %s (found %v)", - int(item), account, foundCheckpoints) - } -} - -func assertTOIDsEqual(t *testing.T, toids map[string]int64, stores []index.Store) { - for hash, toid := range toids { - rawHash := [32]byte{} - decodedHash, err := hex.DecodeString(hash) - require.NoError(t, err) - require.Lenf(t, decodedHash, 32, "invalid tx hash length") - copy(rawHash[:], decodedHash) - - found := false - for i, store := range stores { - storeToid, err := store.TransactionTOID(rawHash) - if err != nil { - require.ErrorIsf(t, err, io.EOF, - "only EOF errors are allowed (store %d, hash %s)", i, hash) - } else { - require.Equalf(t, toid, storeToid, - "TOIDs for tx 0x%s don't match (store %d)", hash, i) - found = true - } - } - - require.Truef(t, found, "TOID for tx 0x%s not found in stores", hash) - } -} diff --git a/exp/lighthorizon/index/cmd/reduce.sh b/exp/lighthorizon/index/cmd/reduce.sh deleted file mode 100755 index 1cfbca0ccc..0000000000 --- a/exp/lighthorizon/index/cmd/reduce.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env bash -# -# Combines indices that were built separately in different folders into a single -# set of indices. -# -# This focuses on starting parallel processes, but the Golang side does -# validation that the reduce jobs resulted in the correct indices. -# - -# check parameters and their validity (types, existence, etc.) - -if [[ "$#" -ne "2" ]]; then - echo "Usage: $0 " - exit 1 -fi - -if [[ ! -d "$1" ]]; then - echo "Error: index src root ('$1') does not exist" - echo "Usage: $0 " - exit 1 -fi - -if [[ ! -d "$2" ]]; then - echo "Warning: index dest ('$2') does not exist, creating..." - mkdir -p "$2" -fi - -MAP_JOB_COUNT=$(ls $1 | grep -E 'job_[0-9]+' | wc -l) -if [[ "$MAP_JOB_COUNT" -le "0" ]]; then - echo "No jobs in index src root ('$1') found." - exit 1 -fi -REDUCE_JOB_COUNT=$MAP_JOB_COUNT - -# build reduce program and start it up - -go build -o reduce ./batch/reduce/... -if [[ "$?" -ne "0" ]]; then - echo "Build failed" - exit 1 -fi - -echo "Coalescing $MAP_JOB_COUNT discovered job outputs from $1 into $2..." - -pids=( ) -for (( i=0; i < $REDUCE_JOB_COUNT; i++ )) -do - echo -n "Creating reduce job $i... " - - AWS_BATCH_JOB_ARRAY_INDEX=$i JOB_INDEX_ENV="AWS_BATCH_JOB_ARRAY_INDEX" MAP_JOB_COUNT=$MAP_JOB_COUNT \ - REDUCE_JOB_COUNT=$REDUCE_JOB_COUNT WORKER_COUNT=4 \ - INDEX_SOURCE_ROOT=file://$1 INDEX_TARGET=file://$2 \ - timeout -k 30s 10s ./reduce & - - echo "pid=$!" - pids+=($!) -done - -sleep $REDUCE_JOB_COUNT - -# Check the status codes for all of the map processes. -for i in "${!pids[@]}"; do - pid=${pids[$i]} - echo -n "Checking job $i (pid=$pid)... " - if ! wait "$pid"; then - echo "failed" - exit 1 - else - echo "succeeded!" - fi -done - -rm ./reduce # cleanup -echo "All jobs succeeded!" -exit 0 diff --git a/exp/lighthorizon/index/cmd/single/main.go b/exp/lighthorizon/index/cmd/single/main.go deleted file mode 100644 index 7661b160dc..0000000000 --- a/exp/lighthorizon/index/cmd/single/main.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "context" - "flag" - "runtime" - "strings" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/network" - "github.com/stellar/go/support/log" -) - -func main() { - sourceUrl := flag.String("source", "gcs://horizon-archive-poc", "history archive url to read txmeta files") - targetUrl := flag.String("target", "file://indexes", "where to write indexes") - networkPassphrase := flag.String("network-passphrase", network.TestNetworkPassphrase, "network passphrase") - start := flag.Int("start", 2, "ledger to start at (inclusive, default: 2, the earliest)") - end := flag.Int("end", 0, "ledger to end at (inclusive, default: 0, the latest as of start time)") - modules := flag.String("modules", "accounts,transactions", "comma-separated list of modules to index (default: all)") - watch := flag.Bool("watch", false, "whether to watch the `source` for new "+ - "txmeta files and index them (default: false). "+ - "note: `-watch` implies a continuous `-end 0` to get to the latest ledger in txmeta files") - workerCount := flag.Int("workers", runtime.NumCPU()-1, "number of workers (default: # of CPUs - 1)") - - flag.Parse() - log.SetLevel(log.InfoLevel) - // log.SetLevel(log.DebugLevel) - - builder, err := index.BuildIndices( - context.Background(), - *sourceUrl, - *targetUrl, - *networkPassphrase, - historyarchive.Range{ - Low: uint32(max(*start, 2)), - High: uint32(*end), - }, - strings.Split(*modules, ","), - *workerCount, - ) - if err != nil { - panic(err) - } - - if *watch { - if err := builder.Watch(context.Background()); err != nil { - panic(err) - } - } -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} diff --git a/exp/lighthorizon/index/cmd/single_test.go b/exp/lighthorizon/index/cmd/single_test.go deleted file mode 100644 index 58620d2ef9..0000000000 --- a/exp/lighthorizon/index/cmd/single_test.go +++ /dev/null @@ -1,279 +0,0 @@ -package main_test - -import ( - "context" - "encoding/hex" - "io" - "io/ioutil" - "path/filepath" - "strconv" - "strings" - "testing" - - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/ingest" - "github.com/stellar/go/ingest/ledgerbackend" - "github.com/stellar/go/metaarchive" - "github.com/stellar/go/network" - "github.com/stellar/go/support/storage" - "github.com/stellar/go/toid" - "github.com/stretchr/testify/require" - - "github.com/stellar/go/exp/lighthorizon/index" -) - -const ( - txmetaSource = "file://./testdata/" -) - -/** - * There are three parts to testing this correctly: - * - test that single-process indexing works - * - test that single-process w/ multi-worker works - * - test map-reduce against the single-process results - * - * Therefore, if any of these fail, the subsequent ones are unreliable. - */ - -func TestSingleProcess(tt *testing.T) { - eldestLedger, latestLedger := GetFixtureLedgerRange(tt) - checkpoints := historyarchive.NewCheckpointManager(0) - - // We want two test variations: - // - starting at the first ledger in a checkpoint range - // - starting at an arbitrary ledger - // - // To do this, we adjust the known set of fixture ledgers we have. - var eldestCheckpointLedger uint32 - if checkpoints.IsCheckpoint(eldestLedger - 1) { - eldestCheckpointLedger = eldestLedger // first in range - eldestLedger += 5 // somewhere in the "middle" - } else { - eldestCheckpointLedger = checkpoints.NextCheckpoint(eldestLedger-1) + 1 - eldestLedger++ - } - - tt.Run("start-at-checkpoint", func(t *testing.T) { - testSingleProcess(tt, historyarchive.Range{ - Low: eldestCheckpointLedger, - High: latestLedger, - }) - }) - - tt.Run("start-at-ledger", func(t *testing.T) { - testSingleProcess(tt, historyarchive.Range{ - Low: eldestLedger, - High: latestLedger, - }) - }) -} - -func testSingleProcess(t *testing.T, ledgerRange historyarchive.Range) { - var ( - firstLedger = ledgerRange.Low - lastLedger = ledgerRange.High - ledgerCount = ledgerRange.High - ledgerRange.Low + 1 - ) - - t.Logf("Validating single-process builder on ledger range [%d, %d] (%d ledgers)", - firstLedger, lastLedger, ledgerCount) - - workerCount := 4 - tmpDir := filepath.Join("file://", t.TempDir()) - t.Logf("Storing indices in %s", tmpDir) - - ctx := context.Background() - _, err := index.BuildIndices( - ctx, - txmetaSource, - tmpDir, - network.TestNetworkPassphrase, - historyarchive.Range{Low: firstLedger, High: lastLedger}, - []string{ - "accounts", - "transactions", - }, - workerCount, - ) - require.NoError(t, err) - - hashes, participants := IndexLedgerRange(t, txmetaSource, firstLedger, lastLedger) - - store, err := index.Connect(tmpDir) - require.NoError(t, err) - require.NotNil(t, store) - - // Ensure the participants reported by the index and the ones we - // tracked while ingesting the ledger range match. - AssertParticipantsEqual(t, participants, store) - - // Ensure the transactions reported by the index match the ones - // tracked when ingesting the ledger range ourselves. - AssertTxsEqual(t, hashes, store) -} - -func AssertTxsEqual(t *testing.T, expected map[string]int64, actual index.Store) { - for hash, knownTOID := range expected { - rawHash, err := hex.DecodeString(hash) - require.NoError(t, err, "bug") - require.Len(t, rawHash, 32) - - tempBuf := [32]byte{} - copy(tempBuf[:], rawHash[:]) - - rawTOID, err := actual.TransactionTOID(tempBuf) - require.NoErrorf(t, err, "expected TOID for tx hash %s", hash) - - require.Equalf(t, knownTOID, rawTOID, - "expected TOID %v, got %v", - toid.Parse(knownTOID), toid.Parse(rawTOID)) - } -} - -func AssertParticipantsEqual(t *testing.T, expected map[string][]uint32, actual index.Store) { - accounts, err := actual.ReadAccounts() - - require.NoError(t, err) - require.Len(t, accounts, len(expected)) - for account := range expected { - require.Contains(t, accounts, account) - } - - for account, knownCheckpoints := range expected { - // Ensure that the "everything" index exists for the account. - index, err := actual.Read(account) - require.NoError(t, err) - require.Contains(t, index, "all/all") - - // Ensure that all of the active checkpoints reported by the index match the ones we - // tracked while ingesting the range ourselves. - activeCheckpoints := []uint32{} - lastActiveCheckpoint := uint32(0) - for { - lastActiveCheckpoint, err = actual.NextActive(account, "all/all", lastActiveCheckpoint) - if err == io.EOF { - break - } - require.NoError(t, err) - - activeCheckpoints = append(activeCheckpoints, lastActiveCheckpoint) - lastActiveCheckpoint += 1 // hit next active one - } - - require.Equalf(t, knownCheckpoints, activeCheckpoints, - "incorrect checkpoints for %s", account) - } -} - -// IndexLedgerRange will connect to a dump of ledger txmeta for the given ledger -// range and build two maps from scratch (i.e. without using the indexer) by -// ingesting them manually: -// -// - a map of tx hashes to TOIDs -// - a map of accounts to a list of checkpoints they were active in -// -// These should be used as a baseline comparison of the indexer, ensuring that -// all of the data is identical. -func IndexLedgerRange( - t *testing.T, - txmetaSource string, - startLedger, endLedger uint32, // inclusive -) ( - map[string]int64, // map of "tx hash": TOID - map[string][]uint32, // map of "account": {checkpoint, checkpoint, ...} -) { - ctx := context.Background() - backend, err := historyarchive.ConnectBackend( - txmetaSource, - storage.ConnectOptions{ - Context: ctx, - S3Region: "us-east-1", - }, - ) - require.NoError(t, err) - - metaArchive := metaarchive.NewMetaArchive(backend) - - ledgerBackend := ledgerbackend.NewHistoryArchiveBackend(metaArchive) - defer ledgerBackend.Close() - - participation := make(map[string][]uint32) - hashes := make(map[string]int64) - - for ledgerSeq := startLedger; ledgerSeq <= endLedger; ledgerSeq++ { - ledger, err := ledgerBackend.GetLedger(ctx, uint32(ledgerSeq)) - require.NoError(t, err) - require.EqualValues(t, ledgerSeq, ledger.LedgerSequence()) - - reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta( - network.TestNetworkPassphrase, ledger) - require.NoError(t, err) - - for { - tx, err := reader.Read() - if err == io.EOF { - break - } - require.NoError(t, err) - - participants, err := index.GetTransactionParticipants(tx) - require.NoError(t, err) - - for _, participant := range participants { - checkpoint := index.GetCheckpointNumber(ledgerSeq) - - // Track the checkpoint in which activity occurred, keeping the - // list duplicate-free. - if list, ok := participation[participant]; ok { - if list[len(list)-1] != checkpoint { - participation[participant] = append(list, checkpoint) - } - } else { - participation[participant] = []uint32{checkpoint} - } - } - - // Track the ledger sequence in which every tx occurred. - hash := hex.EncodeToString(tx.Result.TransactionHash[:]) - hashes[hash] = toid.New( - int32(ledger.LedgerSequence()), - int32(tx.Index), - 0, - ).ToInt64() - } - } - - return hashes, participation -} - -// GetFixtureLedgerRange determines the oldest and latest ledgers w/in the -// fixture data. It's *essentially* equivalent to (but better than, since it -// handles the existence of non-integer files): -// -// LOW=$(ls $txmetaSource/ledgers | sort -n | head -n1) -// HIGH=$(ls $txmetaSource/ledgers | sort -n | tail -n1) -func GetFixtureLedgerRange(t *testing.T) (low uint32, high uint32) { - txmetaSourceDir := strings.Replace( - txmetaSource, - "file://", "", - 1) - files, err := ioutil.ReadDir(filepath.Join(txmetaSourceDir, "ledgers")) - require.NoError(t, err) - - for _, file := range files { - ledgerNum, innerErr := strconv.ParseUint(file.Name(), 10, 32) - if innerErr != nil { // non-integer filename - continue - } - - ledger := uint32(ledgerNum) - if ledger < low || low == 0 { - low = ledger - } - if ledger > high || high == 0 { - high = ledger - } - } - - return low, high -} diff --git a/exp/lighthorizon/index/cmd/testdata/latest b/exp/lighthorizon/index/cmd/testdata/latest deleted file mode 100644 index 9f53cd22d0..0000000000 --- a/exp/lighthorizon/index/cmd/testdata/latest +++ /dev/null @@ -1 +0,0 @@ -1410367 \ No newline at end of file diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410048 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410048 deleted file mode 100644 index 6eb8fee0ce56e3f4040293df7a501bffa7854e40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4160 zcmZQzfPmUN*Seg9WlQR9*WK*0K07}&+-_@44Kpw} z_C4@&G{~l;MaKgmHZm}R=&MDUH8swiW-o4VWe9GFVZ}(4L(3R3Q(Msm{q-NIUjS<%}4}4Www{m^j>zuFA zHD0|93p|oHWy?+wR%40R~=pM9l8=0*0dy7OG2YA4$7d0+Rxo4S0{Y!RJLerp-{og5fMo0kBU zMuF4=0VwVyvVy#QO!JNMLqoN*OmlN0j3O;UEFEoaq4F?w3|s*ZRcrK4H&?hU`tmdQ z1FziXq_5%o)He1W5UK0>ee6F-Aryeq1dz=Lwig)po5J1lPaooDk9n+fp}f0^>%+TO zr;8heXB_^|r+>bG(IREhnKe)H7bre&@V_^Azi+nF=6TP#c57{3bAU}XU#yHBXcpLy zyf;>7@0__-MnHa9!4&V`|K70fVqI{#QaU#(Rdp|~#4@lSxfSbx>L-Kj2V!ghBo3An zsJ)o2V`1#kq}M3-ebsr9i!-|N8A6IeF5AiFwuL>I1Jk^t{Iazo&*Ke2&)eM8uP8Rm zzp_WmI#W_li!t)|jN>~yf$GFP%3i>fGlAU#^!K5wpRabRA8Qc)VGuIu!k5aK>W4bD zUSEu2kh>rda#f`_apDdC;%A;uIAzo7W*zK!y>Exk9+Ms^`+&bm|2O`&<%GJyVY_=| z>HTdSiW7>baBRIBCgP*I;GE#|dHQGDESF5aDQf@l2ghwD&I|WXiMUnBR&BL@CR2KW z?@GzpfSjinByMnV0v!epKf~9K%riD9o|(p?n*B=UTM8$)vr?yzQl4kt$&;oNgbjh} zQWylpPBSoQXam_O;g_`NL^)K9v!J-Z%GlW0!~iG&6@$|${((=K%H#NsReLJ!xOdev zWq!cn`+gQ7R{JETeBRgW3slGy5E>NV;|kIO0qLi%C0ESiEA8F-D_?JN6o=cX5{uX6 z83Go@>$GMrzV;cUib;&`07NwdBh;-9jImi8`HW`Au2>_Pfx{E^xQSsr zAz=qTh3iX~-H;LdGykxgW9y#hJKt{Ch1v-&HGphbn80X|G$?GDfq4s_2MFdxpaxmD zko(a57zr{286X*s#DuE=$0eKxDFYZ__5;giZ>St2sLX=_BHdI?V>f}^4h^qC=Qc{h z3s$DWf*YPtfC41MAtX%D>Q@$^8Nl>Kc6iawZKS)Y3YxxXCGqTFX-U;jk{TJ~!J&0&R_1*Tw@069oZxC*k$BjVijc?*r* zgta^xByK}VYb3e}RDV+;4l&9jaHKC&Yx`EfDQG0FV$8*=!gHTT+5N9H`=t9$22&Tv z#YG!IQ$`Au#+7D(c{O(jR1E{cwjEHRwcN%p43PHSB$z%JjbsTD6DA93|G;_hIul}l z(xM>( z`s*Is>DwfU0@ZH-7IPC|`d~B`2ch_#2=mpR9jzk8d|;anQRfrg2SL&Ub32H};(oX^ E0IH<5$N&HU diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410049 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410049 deleted file mode 100644 index e253f8658a74075490d75c33bf3dce311e5fa836..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5340 zcmZQzfB>Zp#fB4WC#ud-U%qJ5w)s~kuVL+Tb*NtTvhlQK&jO_speo_oJJ-6Lgk?+W zZP(rGvOYUMG~8}$P2}1@en!oyhQDHpZ~V%fr78Tj39c2%2|m$b4%HLHD^UfuUTS!c$L0UriG|&kN)hfr*l6T z1C=;D3R?eAdgqeuT4(D&G%|$Wc=cH^oZZ3XrQDpkGdcXN#fyXkYu7$V3sbSvNQs+R zHRaCX5Y62@2Cp0Uum3IT+Q|ClgqxT~hUg)UW98n5dXL3T_DErl{o`S&mfpW$%Hpuv z3z?d}r#iU|5AAfCwR7h=9>re!2zSn|9K}kPR}JxRKQM^4F!Dawws|=y6d0I~pIH!B z0%AeHsU#qs!r zc>dK5vHLchyZJDbb9(mtANP2+U5jb^|9i%VgI;&c!+SJLbb5b&Vo3S-H#I1xflK!E zoWvGohuPPPZ)Wh9yF9#}`fQa_*TSi9no5jB0#8m>J!O1VE4)j|<1u^m<82T(F)$E{ zE1)_SAZ7xoms;JpdjH4vsV6>vsco8lK+$Z5`dyKYZbk93w$lRd2RbnDJ2^0LE3O18 zoead_cmvYt03;5U6R5qItz%*A(WKWX_kGoQk&83B@)<&kLN43M<+g=Am;=+8_v~l> zSFX#|lLGd~t8^74tQ5SlNxfp(>6ahlZhJo~^8~6B_b7V-Q_ci-3ot#%G+p+eRu|W{ zVpILY(j`V;^ffPE3~&*9d)Oq~dd5w2VS!qOvVeyNE*o!k^LF^X-qdf0J=2N@iY{Lb zZDpgfH}gT=;85b|RqlBpaNEj<8Hp;VW+!iCsMN81_cFA1NmKTUn@<)sEm;|(WFe-0 z=H6SkEmsm}AqZ0TGFODppmQ<Jv+z9z0-~uJ9}|eith&{8lB)H$R$Kq*MK&>Y&b*YjaCXHD=kAHx<=qG|zvW zDYb6@G|Qi_C%Ts(JNumdeCLW89^v_$o%1{S_sBL^8vT0A4+}rT*N)6HHYlE%#-f`2 zO66M$C%3awr;k#eXWq$^rW1q>f$CBi1jJ4=Flgui*(m8RY0-%qs2FEKaeUUv1`tCP+t2bY}bLkuiBGsQtm$R?wT2KnCb0)vkiv3 z+YkIXbBGsc9yncDaMw*tZF;Gp!H?3x)O2Xf9AK$X~x9vYMDcF%Nd?7Zr!>nL1DeyoK`=L@5%8mxuOl_e%dJH zKN1RHtqH2WI>Yb6jVU3Q-!=YMOEf(T3OknXRvH}9$|2d#ld@HqbbO>s*NM+`EBm^p zG^yX8yM${ePz?xxOLQQOlBU2ikT_sw5X}Yo7Yqo-2T+yORxK7_SqX}hNf2EK63G%I zCR`pI=Wrgdq5-p^_9rb0vVzJng6bofI^x`nFf9LK#SIgGr(Ioe1;!=lM+{ z#e4?j_$IpCKuRMphk|GW*`H}ok&c$3LN-=wFRS+1*95X^$gOos`*hu~ zvAs&QPpD_xX^*9G>ow0oM z0!h&Rg2~bK{|$a!_IbDCxoYw*&xDLRciX?#)3sj-Tla1Ol_4O2$QuwoG6}6~a`(do z3HA+v3av#gIjEeE!S)05aXi!=C~-ran=GhZwxGKSYd#(%Zlff;23bBPIiI2Uorrw= UkT>BF+4-30F$@y&F)Z%^0PbzrfdBvi diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410050 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410050 deleted file mode 100644 index e4e5598abee9404b292accdb2a25effd7bc2e25d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5136 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 HoX!9MR%3pG diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410052 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410052 deleted file mode 100644 index 2aa528231a7f7af967bb0788b6cd99d683b1273c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5052 zcmd5<3sg*L9KTZ;6&gwrF`Ay^QI^u^Wr`$^B$I5yW~LO`q!?6ccL=FXCy!DnGDu2k zYD9xWPYLZ7V$C3(FtK*Cm96ae-MM$%9($S==lIT=e*r26clO^BFLa$>#5>SOe&i4(_*ep|?+yd840?5?1_NQUilYt%5dVQniOV&l>j;GLK4}=+@Iundff=y%|rEOPSUc} zh~!ZwJjpR(zM=-~J7A=z;Wd()@T&7@;&GRCl@%Aw=0w+CD7$m^EqjpTmEs$Z+nCtcYfnhReD23; z#+2h5AFi?Tj5W2G9M}FQ!s+Vtb@z@^A9pL&XQu%(r7q;5KZQHz>3!eEOj=C(LFvz- z(?%|-NHnUPUOUkS*1d9c-YU5#XUxoZ37-@9O-Fr^kjSn_F;N zoNkg^#FmGj#`DoYyP za7WDde*pX`Ij~$@-GP9&wUu@3tw%IA#|b_JnI(Fu&aDh(yyp53XH3tYn0&JCFQ`ZQ zZVIkWLh}P0Q>SZFGIi!lS(}&-EUWw*g*H_t60hPR6Fm4?3{FW~aDK~`g&WGZdb3qF zs0Es*oDbW6fA0rLus@^JSz41y1`g4=+-RDxYvt09{50Lcv&k)+jco4fd&lr3nk&a9 zRW-YoYyoL_ZEf!GXXhn9ChlA0HnE`XrA9vQbr|CSjEBxE};sdc%Lx*s_qR zY0ogQnDROw6S=Dx ze%j9@U2ne644hG9);a2g2Kc<=IPpY970)(+$g0D`Kpbcqe1i zrGs*_H!dFve5tVJ*B9_u@nvc+%Pq&+8*Q8GH9Fwb%{K4HQFLk!-`^FB%J~QyjE(h4 zp!)%n;T$MqHAROM*l%=9`C@zE4(@R@U06~<$CeAq=gj_=K_+U-1M*Gkf zoFkar|DKB=0MnEDuZ#&|$LH%?!}dAz1<$E3QA2c22zM5=e1=o|AmZM;?F(=ag*t&6afSBO9@dauq+f#aS z)N?_xZ9F|#M>t63F25j!`6A6GAn2V$tmA%>b%|cnfYqBLue(fu=K$XDeL;>XW122)1q<9Uvx{SGPte96^+; z^wh`pnO+=)w#0X+F9onEen-I}eY&d<@xuFo{Jc{jF61@Np`JMsiB61xBj~A5%p3Ch z(;ECdOx7;k%s(e}0RCYPcph@ze1$ll zlSi*$+GX;qKl diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410053 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410053 deleted file mode 100644 index 25b592c2eafa3346a294d62924ece5ff1aa8480f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3896 zcmZQzfPjf_Kcv_(9FQ?<)R@MS(R8qS*&O*L)8l`f`*8V8x7jIPpekXuiB?m&`u(>b zPj=e1eokVml0vQ7(M8#z@$)ndd?WO~U$_&R8s4I7j#+O?9&uc6`o_pWw>)o2+x_R1U3kJy;bJuMS#fi7f~yZdrcqijLofanSLZ|+#)p*-XE6}z13eEv@PKYuy?3SO)}dg-L;6HSTy={&Rf zA8zfIS6^uIbDjRFglAjI+E@PBQvUy(h3@=}$n0Gx*D09$rs@Joe0#Yn{=e(8MwBKvV!+AV2^-WT~xE^8qa^H0NqfI(FCEF*Oqyp7| z^nvvfv=6H8rS0YNHvzVq;hc5Jj63W#ZI4ZUX0>$9@fiY7&fi~_aRX=`lVgadUl5Q1 z1L>!(C0ESiEA8F-D_?JN6o=cX5{uX683Go@>$GMrzV;cUj?qvTrkoM%KVTYr`TN^+ z-uv^@w}qVWesnU?V;cLaJ-hX!^Jjeg_qcoO#G8{X3f~^KdVBg^{>iQE8V#%FD(u#N zdcJES=kwn-3QyLu01X6(<(wre3gkALa6UUB|JP-i<_0!~MILL}HL|?c{7YZs`1TV6 zzmo$nJ%Pd=7LFiV!Yk6)Bdy9fyUf7MI54>?KiS*F)Z5Y47EK*PgGFG9YLHQKvM~F4 zla-zGUY~Jyjp|YCD1OrBzAStGKal!hS7#u_z(CL~KsDC0PJz_|2}ZE{fMJoea{Zci zeyPn3J#Jw;?iAh74PIFF(j41dia;$pBH{(f8Ps3QRuH1Ej zzaYFjRsNQv06Z+1GZ!}>4>~8iWqZ;3?_9^16|Q}&F7{KR+M?t4cd?n0+mONn9ClEL zz|#pq{lH`nayQJs`{Ih1%+CGO_fF_A+uOimU;c|J?;Mw$oqOwTm{qF&?OukBi}vUp zg?X2O5$pz_f7>z&*Pakh)9@7e{?jFjPqtEam7?lBcmL;Q(H7EkmfStB-Xnkc*U3)- z8|0;Tzj9`h*>R5ZGTX{PhsH@&8J+zg|1z)JTJkAeW^ZBof_E1lg+Dp$FK(B#K42xg zS%`#%t6;Gf*j8{pg0P^j0J$FqKw-cPOdBBcz<>zLh zpw+do_yx&<%_1T$iO*ZG1cJz8$nFKDYjWd>c40!9n~?oSt$1Q6t7=G_dj3WgyGz3- zVW-b+wb@y6VaM&+Ob%TB#5wm6B$R>W$bTS!#UqFYa(_Xi0G2P{

e=t(eBLd$)kb zfa-W z`imNI2o4jZas(XdBBEU0mzA$xoBDa0M}g7PM@FlzCd_VSDKehrd?-+0OC(qkW?hGz zc3@!+Nh?4N#I#kIetl?w)+=BukO^eNq2egvN0j+LGary(KGw8D1A8d(2S%_U2_P}y tAqnymGJxe}^mG8y3yVWgJ_nmc?Y1e{A=v8^SeVenUT~WjyS?zR0RXwZ)C2$k diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410054 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410054 deleted file mode 100644 index 6515d892d672c3595c26bc913d3d5461422f65a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2820 zcmZQzfB+v`d9EwwtuY0f$=X&EHt&4(Ra&Vy`L)#K8Ag--ewg+Zs7iR^+Yc#r3ZV7wf76 z+j=KO`NxB7N?LS04`L$&BZyw1a#mu`+)_4Q%~{dWYnE6aUZro8X(4Lcqd$A=>D&*- zKqU@U>>fs+F3f*yFUkF1P!OcCCFIF5=7OJ^ zk^6rnq^a$f!T??naX(}-i2|PJj^_1~dt?(`-kH_rMkGDbG#K1r( zu7K*8pqSx>Qd-%;v^DV)0xw8N&RpRg+uhVKx5rwyV}on$#C73282FtWfMEcNFOVJ> z0LLGUQ<_yh<4NV?YhOxccC2*2RbBnEfwA1;0LzQFZV5fPDtkfdWY4C;lrw_O1;(wl zcyPXI&HBWQNv03_Z~7leUo*w%NemN%Z?9req-#{yQP%L&8+QI%a&Uv8!m%fu3rc<) zN%uvWt-AX*%l5)zZ!VyLU^nfHD_$}?_fOwDp~Gx%1B-q6FQ&Y6Tyl2qt+!!Tsrt8j zp?+Wis)xB7L`!7ldb%Y#W+q#>`j;Aerst%j_@pJ5+uEY3V_?o)+oiW(e8AvfO5OfPrjrFWkV6{Mk5$rx-SWNN=st6Qu z6aL7eyE^~&w<%Hw{yBd9l4h=Jd*$?euLn|B#4dz{N_|}H;eFw|$}HD>t{Im9_p4{j zJblrkd~N&!KA>4lfr-i0JGU8Y=?2d|6FKQMpA}z3#WBH(2D_J0ZcUe*Z-6ZY#U}(H zhXqs!9G=X;_y&a)7!czhre7Z#koCayf@qi}NMekjJO$$uW&Z1Rpfm_~6HG6N#$rA! zZG-$lOM58s2Zpne1dy0;pCacykRUTy2I@bwauuW&+QiV#Z3EP zVJHC$H+WbREE^dZ#I;t|O8~&vnJTHKsr_ zS=(yD=AEy;N-Gs7zm}Rj!)Vgq57WMWud_)#v-o+>ewh;-uM?+TXc9LyXnM5&l2Fa# z9sk_~I6yWfEjnHdv5|ohL~o51*tEM=!|&<=EBB=jw@x_8AKo15E^{QHdS4UEC7W)b z5{H(`KZV;T{Ce`f+ezh~2T%FJnT{%#uJJd&$Xa)h=PmDasYmyBShmU7Nae5B*u7=h zDc#F!gB~8J{xmB>;__NWN0!gMsqRygI>VXo{JEcbx1?|)->O}26YI*j`*x}Yg>Q(y zm}vMRXxj2G`W8n5?*H-i&_xD9^Zk#V)5hpTAT7&tHzef)}fgUOH*|L{lPvI?rtW zhg-Yl)fbxlT&I63;n|k5_LYCOl>a|xp*z3eW|Db$kA{g(@6S&RDgXYa2E{aR$)28* z*rMz(`&#kM4E}PLhu2e|ty1b*IQ30aiIGU)$;qmxjIU~icPV*1W{-XhiYG826jwk+ zOi;{FnpHjHN#)~fUrJ_ntaQIsUH!6wvE1SS%Zs;e2|c+gdl~qh9DrfK22>A@GawBD zAU2p!P(K3$SZ}baGg#xCB`XT#HkxogJ0btqWtrv%HiktWYuPojyw?0nU*q`p6Ht-3 zN7)OoT96%JHvrRtmTBLby#9Up7nz=YY*?PLSX+7r-sroW=E4=t&RCjds zoxFXitKutuKiBJa`Y+k_;n~9(`<0o$S=X@u%>wzE;Sj5{s>`#7mKRrTuLYwv_ICfAIr( z#;mgmwwCLkyf!j!`SI!_Ywg40Bwqi-c{+XE&xG4#+iI#nd5Gyp?53b8T%R7E{5_3_%zrZ$v;tT>%+zk~2`HdMEr_4}3;V=QliPrKz2|zs{ zy%=U92_P|HrbEIV&I8#E0#N&bWkNhuju9xv4rLSPrWv~wXzV6fIsk>&U~?NK;RW&+ z3P6fDBqm%5x_Vd~g2M!@TnEWf5?<(bAtyM>+(u#?@|+HZr7v2!36u}u>5Axb1xXJ) zhJXxgfx~-__f1Ke_EXmlyYqw9Gh^SYty;eL!Q8XgZrl(~*3Mmhf R;U*NjkvK?9lHCN?003tm(hdLs diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410056 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410056 deleted file mode 100644 index 728fcd2b229e23b205059769a2aa299f7d5153bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6084 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 Ljz{k!!D1c&OB8C1 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410057 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410057 deleted file mode 100644 index 2ffa35e1d04a7a346665c2f659a30abf40515597..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4876 zcmZQzfPk!>Ld##)^-tV+L_=P&=tpyXRL^aL%oEwmMK7{Rq*_b?suKS2?)j#WhI2}7 zHs(p28n>Tc&Dt)`-J{(Ts{Y~B-mQNMb{dt`POlQHW-a@r&AGO>M>=&%Php3Cc*JYt z2K~2H{vex@79FpJ*vP;LqF1P#mDn@4l+9OjR&?~5CDw;m=^JHQh}!n(&)#}E_k%G| ziNlP&2Gei7oc-nl3WJZg1Bjk*|K^S*9?COrU$M)n&gbux|MQpQui(Y%qnA#aKGBrOpUyLz z|KZkddG&=RKiBD>N_e)VtbOI5E#?2uS?JC$xS3=g-lJin)BE!iL(0FusX;LfT(YO< zB(^9!%)VB9GlRd}<>B?zXRDOD7EXQBRAM9&cyhApDdVeJ;ay4|kJ+OiZ-cmrfq_t5 z0oAbpF%w9=#8GSK_4jIpvt_>-{R?qFt30R9RqW8y1uX_F6R&QFt7hPLasY+_2T&EHU<0WQc6A2nW0X?bc~Cxd(D9*uRFa9hqlrP&_k@MK$}C z%C{6wZfB)VAEi9cyptzQCkPt?)uk{9h@EC&(9i?f55#bgwCKcAAO|GISx{VHWo&F> z0ZODm08lO!>U8*%zpuDIhc`z{eG= z7fhs|x|Uoqi?6hI>#uyh$x$3`r%EhdmuCoA7_ZZsx%k>=u%a2$8lXBDp>B1UzGy?C zilRxC`SGN$yIr?+o#6l6c<({>{seaW0H(iRZmFJSR#uuF8GPy9fo1(ZrDb-US_0nN zTr01XPgU*+)?)>l2M(7*tj?+~&mLM{T(!L>tUvn5o#|TZY?h>PpNg@LXIr~m3Yrc; zYMG&K08uc1gN43^T8Wpq{VKnzxV~f(=XN>ej)$twW>%U{Y7}3orEk*&DUv;#3RVjw z7{TTO!+s^zhq*!$6$H~Pz=E&X-WpjI>xnzg$i#Q2wriFng z?oRm>DPO6Tezf&zen$7NW%o>@KyCp0p=;Xf5c7$X?>es#P6(NB+f$fJX-V>;If6M( zS05~C^Et}Epf125?3cm77zT0#irax@(=@0U2Pke0O$&j@iRgTvd^i&Lf) zX}w&va}%S+?h_}q^Q9NMFrPc3()G0c{k>}rJ1<|)XIvWkpQp`3>CpA_mo6t~?6+8J zbnWtr1ykn5c!G>$DcyMWE|0k8L1CBs{{w^;8&5mG*vH6iqW8~J?AiY^?;U~Knerb9 zfNWTJFao*1pmLD-hU9;+5aBRp5SQ`WCj$*f}^4hyfr<~B;g3zS!=5r^O~L23hlqwh?J#mcNr4E!MdOjbm`_3uMF645&_l0a%!W>L@TEqE3R8LrCcw zrWZuREI|@O2|wb@PniR)H<65iFtM1AHSN&A9!mUy;cO%UBqrRuAU`1kNWB5gw@B## zq!(EZY!(rIC#6jRa|f(#f$UypO9=FKmfbBpMKw`qIhtyMW9;&}l+s8=d z8yRjwu^Wkl#Du$o*mz=?oG3XhaZO6cq0RYS#?8vA#%c@QBL(*7wk%ta*h;viO z9vZs|=3kWbIY`__Nq8Z*A1R4L^!fx8{~)s|2`}2Y4Jkhp5r<;${=SE$FIu^Y0lC~G zy6ukS4`|*&k3+by^;yXb?rFd4S`3qayKIgXK6v`+kG0a|&x>F*AH|7vw$! zKe6zu%gw0_msZ8q&T5%v80Ip)=!8Veqbv3|L%6lhE(>4~ZQa$f!T??naX(}-i2|PJj^_1~dt?(`-kH_rMkGDbG#K1r( zu7K)TfS3uSzH8d+5c7$X?>es#P6(NB+f$fJX-V>;If6M(S05~C^Et}Epf125?3cm7 z7?uW94vsgFJ`e!L=WHMa65}W+F0e8*F))SlffPjTOWVukZvt#J!#V4c8F$!g+8&$y z%xdYH<1+-FoWH*;;|5S2lVgZ)WDrOP6r`WJmRvE5ue5jTuYA49Q5mIh&ve^9Oqk3oN-NzagreKI^+KN?ppG@a!c3ec)wp3P)*$p=E&{+aBFp&`>m{3`*P0qG6&TC+TNhS`C-2dw_OxF&^&OM7`}F7p0Ppk%rq9& z>{lw^QaHJtl{$Tt@;viSo-~~xYzS1B!XO}ant?$>AIL@vlM}0;Vw|8bF*Y`_Faiod z#o%;`f8bN5@;JU@)t*W_?p^gvnICZYzMn;i)jo+SpZ7KU0u?d^ga!rpxPr7m05Rdh zFk@N+R5>Hmtq$Ft9ev_TdqwU#@Bdq|F#O8>y#EJ}v#u(f@8KGet*DrNV$Ut7=Kt$# zv&(p|W}ZKr<8ffmd5Zu&vr?N0x+`A?@dC{Qhsz74w6cR~YvLyaUXYNSxxzcPyQyJr zkF{>c2G`n&>%w<1@H;sG^9v|EK*xATrJvvUXDfi1KDiQZ6djVDpBpAVN0Qz^5@-rUo;P1uO zHB8f;Z_oG|8qwf1jxMTy_4dsK} z4+EeuV+O`4C_KP`2>(Ok4@nP9FNlU&f+WTWDq~@M;>=H(gX|`lUJ#ANd|2Fr{6R~5 zDDek|vylXlm~fwh(=wa~iX#w!`VXz1MV14bMMM~rl73;%fTd$(_fit($mW3UKoUS= z!mNknZ#WNMn2?_iK=z{8jl@A>!d*dZJTasP@7lSnUgSd>}-W|~T9aQM@K+OVENFG9B!d2k% z8@Q|hromdMN|by-q??V-gVc`WY69$RfCz~ylCe(q;?T8Zn|j13rkIZ^-s diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410059 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410059 deleted file mode 100644 index 7911dde3ff96236dc754c033c8cea4ba3505a6d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4876 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410061 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410061 deleted file mode 100644 index bbd1823295d4c4f2a435d19a9c2207e29812833a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5944 zcmZQzfPgirSD!xOaLM0wic^fGj_2i0k#{pApBJ6|m-PCV$GL;PKvlw$Dlbza3OBCc z=g~eMwBz=_IUMO?-md=kV)21XFQHCABL?ph7Ms|T#ymp_m>G($e0+b4Z-eDtjy?#$|X8&)fyKag-_?ah|f)93o8UwlyFbo|Dd z4UL=UC+XLR`B$8I^YEt8*`2Rg+qoWW>JB&99dFpPfw!`@_4{JgcVE+Xu&|z+-x~Z^ zd}8{^rOPhwKcN^G8(cL>@nM^phUSHmKRoMrk|zG#cJi?!gJ=sc?}Kfdm#2VS%zXUJ z3yVJ>76hD12GS`EKHd%>dcysiJC=AT&$xZXE~h%5zf=CtUyi?m7psq6I%)buQzCyl z&uspOTf61e7n=NBr++Hp*_N{Qm4CLB|37D;JHOy&l6iQKhKWw^&rb{~|Nf>1#WZlq zo}QD~qU z9;62dK=B8TLxTDl7R=Q=V7!;fB%qC#GMo zF3Z_=YghcPeO&C`65M;%AH1sR=JmsacdkkOm1!-rxpTd&lC@ZY27<$YEpLXk_|G*9 zn~JukM8$1t@QeL*?(@nBA=TQ{U3!N8vEVS^R;&lApA5ucf5RMuM8m^Gp!Q<6j)k#D zlU}3T_f_XbF3#x6X9y_@xojtw+ZOg<4or{dk>HC}I=4dO8=qHNq#RvU?08tL=AU)q z0lqJhLjMxa0o93nl)Zo{X9Bwg=x>R;t81=nF5M>n%_vRxHam;gHNhuRVK&;zKl!pQ z-MsU+O6`M(oqC%4t{{eD;j?CyOJ8{H7r(}AZRFG1X0COf1?mQeT#-j*dh9$WuC95n zusfvfXyl1)%<+aC$98Hh>zO~(UncGB(@h06E_ygkK;R5?Wwfm-c`?(`2mOT`&ooo z?UR`Dd0#WAjA9B14GQpa1!;kR^i$W8D`xSP_HO-^uQxf0!|haw#q0760Sn`GS~C}4 z`wUXWv~H;bL^T5=)U6Jic#MAiDB1YljOCP-8egb)jKuf+)%~x6H!Hu{%G8(layge% zoOjWWH6Lv=m-tWVV=dfj^LSU#6sI$`{Ih1%+CGO z_fF_A+uOimU;c|J?;Mw$oqOwTm{qF&?Ou?fNO_GB>^@*xlgjgDxv8TPdFEtG-Z|BV z7KbbU`zLzG+Y3BMZ%bYI$T%;k^uP>O|C^OR-pH4}6zUYy;NSeZ^Oxt7?QY*X71cO^ z#vp|JbH&-<=K=LiD-hpXHwgi`baJ4`NBz~awCoKxHf=V)i>IaxYBHbiM zV>f})9tZ=&YtXrklJEkRy(j=F;*gkdCEz>==fUF;5+-PE5l9{sZGr0{Scb2Abn?i{ zTcSYoHvp6D1SEUFOe_vU@jDUbZ>lN!M2h(g$ni~d-GY=xko|zg{S3!)6CZ7up)9BL zN&ERJ^P?j3ohP1IA^PCOa?8bn;mJlbq54z)0|Af?GlCJw{RfqUrAt_wfPsj*gMoeh z#~5h+0jf(t^)?*9ECC82G2zni_=Ji;^KlEl%1^gvt|c7lRdo+y5XIyq+bdZ3|KlYu|#6K@hO`2DPogfQa@rgY4Oq zInXvbC=a0I10)U-6KXiLodV|}%1E&Nz_4wH%Av$Jk#4e}v74~wk3r%#O2P}|FO;}K z;vg~Mu?A9)3}9s(dj0_E1?4-Gb^(duMLV}4mA_=T2_+1W0ttx;4k8dAMJ+fyKvGcq zk;)TLIDzs3*bE}vL~0oTvK7|9Lv|-D?a<3!usuj^e~`Nn01__XFe4%ifcmIjCNgN1 zNglBN_IIgib=fTOKX)IPvGA*|SGmzLVSh3^^8-FDsAJLl56EE(az7|O;q?x|z8O%1 z)P=V-Ks})R1k#Ue9x?|-9H+`_k8mx&(H%ZXgO(3_!!VBK+7$k0^ zB)mZJh!R&w93&<5C0WgUuo$yx`>p(S7rci}vUp1vw4HAFwc? niM?Rku-gmrFQ|VHwwKyt5ny|XC?Bb9FSH!QRxU%G#J~UmR@7}m diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410062 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410062 deleted file mode 100644 index 9b942201c7bf38440ff06066d82f176f6d49d0a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6732 zcmd5=3pi9;8{T`UltdR4m1{!EX&S&dhmuOn>}O>v?9@WxwC|z3cnFz1G?bK?cjqtFcWC z{UFNRJLH4jO$pCs(wVD1HkpqsdmcADI-O{FkO@EsV8X=r5T@9;`Lq&V5y=ZDp79YOEpB=m26Xm z$qrvb-yfsjak5iY@84&}lCrZ4qEk<>D$6{l9IOe|_di18JbmI+RnwRz=l^yaO$c?C zRFOZe_Daam>sqmL@wwNzE(?pVT>s5iFJ!m9P`S$u?~tFIqpW{I9hZ*ZZC!QIVOLiV zWiC1?`~30l$ugz`GKggO6tTwaE9V%HxlmDQn|=;H2T-x$C(q&D3Q7(t360zVn=`fddcq z7P5S6U6;_JRJAn@^?pPc{eAAX8+J{aQB|XDFS7v$tc(;Z02&8=BnV#oW`$7PMTOE6!t=JiR_)3=3QK@6Fq$~fG`jVsS*THh4H}R2IXLJJ$wH)sNmQ{Uq4@pmX@~868PXB9ENAC zwP_&*I#0P5Y^In~Uuni*Sr;}~>Dg0m&5Z53wZ{_RN!AXw))pq1EcWNYu5t@HH6`Fs z))${eG3!NEvHkVl1a6kl)5=sonOxNcK_u7pgaC?jr6x!BASXMI=DS6`YgeMB3+H__ zDShUlx-!w_`ss&0+S#^GRbzTT_=gr;D)6pL)e$qwx1fzv2yJ`P8!f+%bw(Jfg-Y4o z;~Wo4Mk@Hp)^3+>A3)cbKV#fjl~!JVM|JJZz2?UeL^KBxQjb7{0@eaJpI@LnUWD*k z46jM{qRm)yWc?V7q-z)o8&E&$U}tOuJ0f!usaLn`J!Z&SU($Uhq_QZlPDJ{4B1P$s zy@3s6^VJXo%Ba{hu{Xt(sc?Sn-#I@(SN%`UWpZp-B*p1MZ*@uXma8U*U(07te}sWX z$tHc}I!xWsP1MfV{v75_dj3Y6{?Z7=qM4!P4~6A5_MC9sUSm{*+e8QBfl%E=BJN*v z7tZ}pSF0R=CZE-EVnwz!-uDTHf@vjFYvJlw0-ww!L+H#pIOzJ z?WB6KxDJw=DA0$+e#Cr5BhG+uWFe%_^MDLr?7&bO*>uBe!`=vUco zv;C9}!asPfesn#=e3g706_*qA{lIYT29E>ZS{ta*CNka7oaJf;_hMQpsToCa63t}| zX`5?+PSOf{Gh#AtG3MgMOs5~<=MzE zW^IuTEov*`^qM85o)}a5$SM4d5Bq4d>kHckin2O^WD)d@)~oY&Q6BdjjWD zTG$h#;M)1y%p>=ddPo?ktUlylpc`8(j)DjR}N+LQQaJ!tFejHosZwIZJXEOGZ6jvR$RO z_5SjdIawV&9{^6;bY~j@Ct+L=gsK|iUX@fw|9U&10C}eN=n}JFww?HlCbhdgo##J0 zdM%GGM_dtGnX`#?q06IMHi}->r5?R!|0QsRbhc7Hn}y;WsNJ6L|VnUd69sY@O5 zwB=~d+4~po_s!5S^XK@GwbEpcw!LxSOhsBmH|&=W>)vo=gZGVdnR3Wd+dquy}g&_$d?q^A!vo%URI6yZcEI6lHuIk#V5q|*NE~6GMSLE zGr^V@wDPGUMjFEpvrq99l{f|FV8ntlv*= zS#GIWOKzQoEF%}%ZG>|g*Gai)n-o4(R{lkTmBqTU9+mmco85Ec8kb#QG;XJNF2Idq zyEAAL`9sW!;DiX^2Y|))b0~v;i!UIa@COv;DKLgY;0(d#BM6T<4;TqR2F{-wM?xnt zLHrppOw?G;5FJnt?mxJFur^__1LG(>*AO@XIq8itC&-=f*N?{Sd;A6G#1l5Y4&OK) zkKtm7`Q%?`Xn2l;`Srj0YwWmvA16K^@HmO5iFph5`LLKj;3M2VkH3g93@=E|kHLCC ztOeLS1mN(k>kyndv9Iy^ipbypmtD-x5PJjUhv=U7h}S89uASypZSHZ+Q(f-GlT_s_ zPvh;EPRT5m&RmFr;CIJh;hhIQM645D`NY78=L`VU7j2Zl&l<-FIilt;Iss+jz6t#$ zMo5o%?#yhu9J1r1B*267KN?NQ5%my+_~tHv{&+3Uq;Jtrtalg%fzQJ{`Acwz^$`4# z@T$slO@&KZGW!f`pQEBj%IyPx4sVZUy4?AcQ)ERU?jsljpzx?bLH7%;o5)MJk6~rR zZ!ZLqQcYb)0gT}HmogCI#t16l;mOm)RKvgFasaar_6koN$rl^JIMJ%cm=okq_=~&W z{~+AH$6xRpdNgAA@ADBB%CttY;H>Hhm8ove8d|FcZX|H}k8i6DO0JN&*ctxy0KB^a z1=YZFbnv_k_<(-@;Im=dL@Y#boB(%52$H<%RuX=1WCi5lcOJL!BrH#p`*^tA#q5LJ z4Z@Lpu@K~*DS1;~z!-BHGIxIvZr|fCm_MTt!y$8bt$gexrh9$s6-`Fty&hRd~ z^xgv2Ly~9Bg9-Ol@OTfkz7n}hME-9NFEbhd diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410063 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410063 deleted file mode 100644 index 2ff80dfa664fde3f1705f5218c0e55cd8c30a679..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6004 zcmZQzfB1z!}MbNBmn zXZh8LJr-u7dK&jl&rIdK_mb&*_U9Y@GxClKIvOtdv3$Sa%VQJkm=bKwQ%a2rV=BOz>||zPZ?j;3hz?#c+4LCcpJn`3=D+g z3aE}1h?zj@Q~U#;GL^^i9jo?K+HvoyXUhD5!}t9xLag>lO!>U8*_VN_Z2$9@fiY7&fi~_aRX=`lVgadOAwF& z1L>!(C0ESiEA8F-D_?JN6o=cX5{uX683Go@>$GMrzV;cYPNJyh7EC!K*nhw@CUxrN z7N>|K@!?4d?L zn)xi}+H}j$te-E&4>S-QmYzp~FIMT?3XN}kUTKkXbXBqAVX>Nj)`_buhnX9Jfet!yx68t|P286|LP zT+Ui%<-qi2K1hS?*;Eh(0*qjDfqoFSnz%6NU74ig>A#1s?I{a2jGOqUPkYko!^WbO z`+H4g#q@h8R(Tk2lZk#2Imz_vflvna)odcO>b(0y&R5T40mTJ4K5}?|e|@C+{GXIz zt)b9|a{Dm8Du(FLI?rovafv^3q|Jnpi(VE${cG5|v7n=-kWHu~V zc=to@YEYRW?osvvW)~CKEkJ*FRGkV`?hTL<=6tkp-Ol%_XZTomePQejQn#PFf$ezO z%twy%_h0P%o}t8YP<1-*zB~OP>z4URWv+c;&*{7S;}>428yw^|-(Rk6U?2VbPWs1n z3-+@33(Rd36|SpdKbY(!F^etrvcUxBM_2PM&1;f7`XEz;(?WTF)WaOF3;N5iye%<$ z1&UK}_!+)-WS+4>@ys+9)$CU)-%>caos~L$l=3|DPM$QKAZ!R!m%<<*cA9}f!vx4i z3BRO8CyqeHI17pktc;CKOpSm7P%$`7M0vmz5E>NV;|kUbCWy%A4B)&5(ZUFItHX9h z{hh7P6vL&}-vnA#^e?T5&_Ac(bY=h9j2X@zU+-S{b@|weswX{{+^VgPIn94(QR8#v z>}0FJy|3S1O7}5$;07AUYIDQsy^u=Xy&kc`IvKOs%OZrDcZK#|-}L3r!Ts+4!Z@L> zO!*H4KsGE)7=hehP&rW8GDGtYScr%)5Yt#1ehp|Gs2o-WY66uZZ~(IeD1gL-OM~MQ z&I8#E0+755D#NEk0DX>o{212C3(uRv;*tWe5>qnng-?#F-CtAMxg6O+z%WhZ28a1PhV?5)&S3AU`1k zSe`~t4F92tSs;L(Cn2H`5)@v*aLC;O6C~Ka0V=eX&UIsev~ecE^ucJPa6n?hWFc(; zI1gTLK3)#7jgs&JwNp_5Qp6!K;Y#3n3@U=J zoB+w8v`YxKch^0dZTyEz6sQlF4;UxFZG|$hI0(h>M3~?Fx>bo3^Fi$zcsWOOI~++5 zvLCRxpTTAC1HS{2C%&n)*31m=oV~D9YJ=Wa?U1``FWvWilm5T~s-K8_4DLIDl@si1 zA?j36+Z+R6aVJVR6K6iSP9@fStoe%u_E6#vj9@_$Kw`p!lbpN)PirLl9m9Sk0VF0F zZbM4T#JEXoWfQ0^h2D<`Ta4roBqqsjLdlavj|m|818yUbfz2T^&!3UuT4`i9d2dB~ zXW9#|@IQ^)O;*pD>7BYXroA@kDpWtVKG{F094PKl%043cz6|W^KTLu4e~p3qL1Sug yfaFdjCR`ds3 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410064 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410064 deleted file mode 100644 index b33caa50d45ff3337366c34615cd62184331b5c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5940 zcmZQzfB;2N-Mi}@R|w41GSe)n71;gzum6kxO51<;-I{o$?u@G$P?fN>e2~nxEw>hy zbaFUs)ZeICH|2sibHbH7PWv9T@5{VlI`dBM*O=PZ6A z+9|se_@hBKB`rF>5Mm<(BZ%G_E3j#It%l##16J-!A8ws+l0UpT)LrICK=r;RmP zKqU^_uheAR$``o%bRPr zd|P4fgLf>;%^wPx8d&{o)MVFx>{oty=27L4RX62h4#%W2$Ul5qvsJg#<1;fLzRc{LBmc z1t1m#oC1laF!*>ofanSLZ|+#)p*-XE6}z13eEv@PKYuy?3SO)}dg-L;6HSTy={&Rf zA8zfIS6^uIbDjRFglAjI+E@PBQvUy(h3@=}$n0Gx*D09$rs;!3$J(~)mK!6c! zE--G3w%Y#VeRg%j?1UU~lg{|81pDVZWNwu{>C8L#GS+O4e0957)#iig9e=B5P18_* zQZFp;aD;iis+7bOwfwvXGr56gf&HL(qq=_1{=I51iY2vnnC~`f~CE?CL{$*y##4M z_5;{lpdS`|3VwWdXR^HJ8lF$4sw!6YL9%AK7azm)nP8S_1eGjyFX z|6bl5KR1uqb78mdiJzFp^+T|L1!OGP4~DNDnP+TJJTr|&HT#vyw-iopXQfUbr998P zlP66l2pa;`r7#GHon~OrFa@$v+@7@P#0jVvXF+j+m9epj0Z0*43{I!`2R>ygkK;R5 z?Wwfm-c`?(`2mOT`&ooo?UR`Dd0(?HP$5%5Xi$KUD@Y3jq@TK$TrrEUw0G;Te7(t0 z9B!vdEMAvq2v``e)0(;X+Gmg|)~^qtsu>ueZgrS!@#d_jeo(yX>F-&^lJ{oW$7s%2 ze*VkuH4)EF*L``Z`dF{=zTGNq_Sf7w;o2YbxmEa7Gq*pCIVSDL>?8w&Vjqx=7B0tkK^+DY z=LM+=^@fOYsJ__IASs)$Rai!#k+00hLCDTR+1BX3Z_kb1y?4xYfvWboyb^T>sV2f5 zi~+7-r3`00h0<(9C+7ay8pW`>$Vu~}%&NrX$^%(lAurl(oH~9$YzMm)1RcQN)oqs(h=+t2r6s7a!MNs@}Hh z(VX+&S1~eNfAo2yqT&r5UQj{>#|ObQ#Mrg~=%uX;OyAW(egk4S0G9ut_+Yu?=PYJ& z!0+CZix(yJs-$ydidAe|K4!XK+EwG_rZB?+s0O4Dte2pDP<1bDFPFawu+Z1OX!rE8AQ5O{L_{<4f4K=YU!Lp)uAfD9NQB5g|))!c$9XN2Yv2a$EUmM@K; zW$Q?=RJ==T+~lTzkfHNmVAVm*6%4bq&R#OyXmI6EK0kli2v zsT)9b`y8koBdE@VvKfeU6R>QishdDNoNe14;}>w;+p^K3!oEeL?xKp=oC&7h=Fg6$0k262zF7w~ii zF&aT)u>>Xjh%^8B99X(Vm<(ZIF&}H%p@BV=_yfb)NCHSqxNmXgW%P6a(hJJxpg4r* z8xsAFVLy@p5|a$Kk?1C^l})gC$FLVk0EtPmn?UIn9!^BJi;?ueZ3Hr~IpojT;0p02 zF>0H0)mgr7TdJ;BuzLN`^EN5#zE`ev75Yn7o+Q|Q2Ifg<*a6FFOlKjv6Nw4;39hsT zYUAOoH;8nT1u(p6=_agse~`EhrMw`~P3Uog9I2$lAyMVUpm7^gJ|o6WJa=Sa>5Eq3 zg;HJ+-3LYT2RxSn8Q3DuF-GCWzW7s@1h#K(ObCrHX1uy|gKR{V(<}4pLmS*8wnFt| zYiIt0%7OfjQil`KS7l&d|G@y-Uo`>h2eo_9SQFLGB+gCm&(PRSAh*N9 z3tkTl61Sn07bLm~G@L+&UacZ}z=#`TYXeDi#!`7?FR&-a^ay=Tlj6Si&Q zW&Mv%F3^;Lo<@0reIfKT3hJkV0TKOmagWUUDbTTlUZ5sOI)my*N|;DYs3f#64Clf0 tinf652ezXTZDORnN~D_%XzV7eX>^dd4JD0|=q6CxhZ=E+HI2gJ8UWPuSVsT= diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410065 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410065 deleted file mode 100644 index 13b942c6a252824830638d03b2607ebfb1828eda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4992 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 GZan}7&ZU3= diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410067 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410067 deleted file mode 100644 index f093ddb04064f16254e209f130ea08a765cf2231..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6092 zcmd5<3pkY78~}S(sJk|4bo@eH~=bZQQJMa5`=RF64cy0MH z(m-zW`JwD5&&o?2o-SNgml%6fi?p}c`Wo`5l7h4?(^kY zJc|$k?$cJ>mn}T!JIhk#?6z&!F6iA&SJU`eM_T`+T0(ZU`!E%-Fe)z&&^!inJr`e1 zU#jlmICM)aOUzaEUawzJ?WIn2tK%_@(i6HX?~LW^?%pE3gDgSTY8`Pha&Be$#9gQk zEhN@hW*0x}BigeH`fo7?r4DeyGmFbz*TqHDYJ^CgP8?BNsrw`=B~@%!HR&?tO@1FW zw^#EYQi3<-I+N>KeB?YN9U?ieBj@I27K~V^yr$1Y7N&Tu3Z7*_7C$oJKC-n7?XN*zSaMgrfJ77OzG99|%91 zKVcP^UaJ55j`GIBQ1jCeB$fvWk;5P%Un{_l#0{4FPZL7N^U$7XBi4P;IUwqyoESr~+`L~3 zx0LMI#H|TaDwhqcuO%r^g5&JG9vPRTHVM3VK#bvNw>~wy0`}S;61)nf+9sN4Dd%Pt z$8rMq9UUbfk@u_k=j^2&y||U(^=r0rW10P zRC-v$=kA2T((3#7)@B8$97x!7St~Zz7OWKvZ0Rjiktcg zxh@Mg1hlnem&zBNfaT=w!!AV{0nrQgu&`-m0b!BU@IWY`Br}owzn-qH!DMxriA?|C zF+=Sg-e--Ud3TT5Za=GZHT?Io{MtO3qy|#yNxkLk1I`H>8NuH!vIq6&hC=Z-6l>y0 zEB6kp7-fly87qZbD0whFDl0W3CDj2R3z{!e4MEB}fX43wob45l(K%61Z%;avN~Ns> z6X+bj7a#|SR<_nw7AA-+@+U}ai8A6Ps00DU%AjNnTV7-YYd6Kjt}bddQgo}77L1B49=+@p;i4o9!$x;Ii=4$ zCCoW*np!B|HO(32dfhu?BmU@Mz`Q8^xJSQ+ENHW2+4UQ5%Fqrderuv@xQ4ZTG<7xr zCTwdGSZ?TUKTCvq*fjFhY!TOJp}R@Us^5)YQm%%#HP`dN6DS`*12n&mfFT#%*t}2B zaBPIYHzkhp2~f)*i0xG5i`KJ^Kn{*Ezu^LhBl*inF7QVfR@6Q?56_@$1o+N?@d;A@ z*iMDauZ#)Cj`{0b!}dA;g6||>B8G@haQ9Ord}0cOH_kMNo@J}MYQL*Dq8)wM`GDeU#Hlno!cUHl&@EROL{@Fgmy?7Zt;2_$ zu+3(w@sA52%kYBd!K*ZswRfWOQ`HUZ&I9{*(l;r<-5i>IeTanK&$WR({LbSy98Mg` zU;b1)kuw40+BKAOQvM5uX)xt0V}h|`{^IBVH-hbR`~|KBbvNof~PD(cHhYy`vY6w*Ym+JrCuDrhO*?Mm>?l5Qz6yipJ!y9+#Ln z5?lS$-G*m>_jzkN$~npB0%B75%9y6i(QgFX=lCmzA058)`7<+!A+K(IqNefhCDXo} vGrHW^;&f?%;08FEBl$=^#)d6T+PeVyZMUAWo{9cRwMO9g{0wRhwvqn>J?*N~ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410068 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410068 deleted file mode 100644 index 7329c0c54e02dfd794a2f967e62554069b812f79..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4864 zcmZQzfB=t)ldku^%s$9+(%|07pO0()?OT3QRea^;yCGI{n(v#>0;&>LZfAM5{raN! zTkkwSejwtpko@^MQ#PBiWbX_5sq?33(N*=EDUQcoHci_6UES?(gZjjUchX$sc+{R0 z>wd|N+NEp?vMFiN@$C>B85lwI)uPOsNdezIbJ=GFrGUdXa4M(qAz#3s_$?ZgJ_Eg?}Kfdm#2VS%zXUJ z3%3;@76hCEiKa04csqdT3HNXASmL2PtUh|_r0Ek)iTvq2 zv-uxx?Uq+xX!3KN{;7m#Tguv3{@GIg|D1*H{DPZF=HWdWCOW-8KQW~I`p=Z0FzmXzE|@Q}GPt z&QB|BeqK{PsQOpzbo3PYdru=cfd+#8uszojReSUF(7AfY z7U6gMk7+^uAPiKG>~3T>L+;zRQ|?Vuzu}hn?9hDK6aTMXzj5hc!PA1%UV@F{o5W@{rXSb=ehcc_h;w$_w4#)@BHuDWoMzMiz}zN?N8Q@4~WQE zqU{!=ckx=h|Ma?59QkQlj_ys|H!ay%lJdp%2-}zY zrqds7(#a{=KG6ge0U&)~y#(!ps(WdBx%^Flt!6l9T{7bidrjM8lb=~FU2}Yfz?1X$ zmu1`ln#bfA;^`LzWWYfBscXph4DJAnTxM|2B~8- z)P*T$1p5ydmS_GrD{xC45Y;=gZ1q)--#kB?7aVo;S9<)aJ(;UjRK<1ke`#~^-K~6! zu3h>4{vrQMCV`~WbCy`>xrQ;Pu8_-T1{w%X4~DNDnP+TJJTr|&HT#vyw-iopXQfUb zr998PlP66l2pa;`r7#GHon~Orumm{;<`58_wCKcrs2FEKael8Pgh|IvAmDbqM~S5^(X%q<2&9ZCJW9`tGgUCr?^&-neUU`Fp^` zpI_#yRxDxa(pdKW-OiV67cK~fENh6}zwq~_UHMKfbv?)5TmXd&%OQ!0d?HU>KC{Lj zo>XpP=3vg&aPH}eS=*mSJ@_&=ZBqu+PH-s)WTS)$R1Orj%)qh$l#jrGVA;XIAg;Bt zX%4jfz%Ua@0Er1R9TJyt9>{JGfZ7jC^P8Y@j6g9FD4TG3262-GjokzaD_D39Hn&j{ zUf}!%3u_RK6mdvQxC(Ujus8&V30ivqBnL`gG<)%Nmwqun8`(=$xfETH;R{sRG$5sX0YFQ^YVlv6v@EH4)^h*okNt-0_mnSFxCHB? zVoRg{ps5BH=I}I1M0=iref_%y&^A3NAFx8r0#ir{6Nw2|0kRJnz{*3sX_QDe+0fWc aSkveraT`h+CDBcwE*CZ85NjHRMK%E0O>=Mn diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410069 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410069 deleted file mode 100644 index 5b4dad0b871b3bbda8feb9716bdddc0d68a4c560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4084 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 E0Q!ruDF6Tf diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410072 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410072 deleted file mode 100644 index 73d1d63c7e147277f16d51941eae375f406b7b6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5316 zcmZQzfPh11n)kG+DXjVuH$lx>Y27Aay?bqsO$~S*@0%AXs9U%KRSCC$*0JTC!;!3T zKuMn6+j{r@sJ*Ksb2zx>?8w?TFWTlqL#3~KnAUZ>%T0{CGqc`A$-G*OXUt{Fa=>L$|7!V~v@;`z4z)J<=3j*E9)uN?JrOymA^ zI7>y=CA8!W`J>mY%9ZNivXWYJGms6e3-zop+FUMcOi`7Rjoiu%-DUm;&XEy)C zt=;nK3r&8m(?6B)Y)e`D%0FAm|DUtaonLS>$vnJA!$ha|=O>1ge}7YhVj8$)PtQqg zQFfSpt@vgJf4R%U>#5IHDRnKJ`lhMGNF?y&WYtr~SGB^slsq1@M?c;MaT5arp|}F7 zV*z3&koqa_uDx|E<3DYOp#d z033f1CIf?<#Oj^WGv@wjX_U?ry!Ie_d(qDSD>G&E)^z{ln^m#q2uPjm*;JTvMzFcS zxGj{((2x+>RrmF%M3?*ArC}3$3)1vtFKM@IWz-cc%(i&nx5}%uh5h~Ax+{F)MRpgB z7`WMYF`C!s&HH2V=kt1gpn+gNbWM95Vm@*5UFQ|T2_X}1dkS+YElFN9M=;0f>VqY1 zK1UfC)CCxX{W2IB!!m$+P}~kolh2`I90kP%R)!`9rbueQYG2x3E`JkXs~OH&m&~}s zUeos2?r;q8jSK=ZU?Ba}wd9Ife5Jixf92~Ingl+=}%;^%H>@B}|}h0#P7wu$(~c#cUl5 zV~-}iM!D~+&Wl`}(Us2-QWSF8PA<1C?7bdnFJQ`NR$N^YrTO2y<9vSS^anBj&Hgd& zOpm+T{P!pi&|%>4t3CML$nJQN#p)js74mbe&o7yfcdzW#;)gFp9&321Cw+y6-%6nR z$v{lC@cYiR?TMl1ock-+hbr-~7p9f9L~IlNt0%%@DgNR>?k**uT`1uPb_+24?l_0V z7M;}(NLp>4*dx2SkA1}q&Nch%Rp$6~i)l!RpI>~fa8+x*lbhh9#h2C}yR)^yfn6$m zX8+R**<#ZZ9WJxO!mqoYz2$z%`vvE=y*Qt<$w6+IG4w$~c^%__Y!SZe0Bejz&n?!+%HvqFczVroi1B%~?FrUBC zXcj5v1JfrWzKJe(k@UbE3Zk(EsJB+5)dR80)1IZqGX*E|xx{TwN?BeawAgBe>Y7VV z!UrJwiOR>|HULOH!EzO-#+p+Ll#fAW>m-mKWPs#OBqm%1jx>-9wjY>}!R=6>YLvJk z&P~jqd`wF>Va>;b#BG#>7pQ(j0Z0*t#Dpus5r=s5F}zHsK|VwAJ7M!5{;=4+iR^q# zbp204K7MW;pLRD~V*R8?R+FxrzP_I|_T5ouId(7m?x(qPTmLSBggi0%xJ4WmO9cB3 zz;=q(EQbToG8QAAkpz&KFw=3>#}NC0W%+TaN|d-E&P|dVXzV7e`FN1Hjgs&}&zHz` z1}Sj}&Z{`;V|YF$F}!H!Hl%z;jGK7QY=NaOTDb|O-Y2^6jpPq_E(0>KMVygLRiftX z<3di3_XGcC&gNsx{4AQ&wIa8lx8&#F<8x~v`qc&g0|Al|j6m)$sM#RDgW6ZzP(B0U zK01TAjNhIQ(0+P4P#>r-1_wy)L}J3F(Zd?n_5<4wOl$2>l_=?-I5$mwKw~$7+ztyb Zc={hCZlff;Kw~Y`h(q-90v_og1^|-1y14)V diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410073 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410073 deleted file mode 100644 index 12c2708a1742789404390329814afb6510fa7d77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5080 zcmZQzfB>fGZ@2X2lEdfwJ3UG*t^Qj#ea54?#qH@eQ$MVGzV6F4peo@*XPWo4sVS`b z5;sB3T4~)TVZD28k4+7D9q*eLDX3exIxIZ#o9%$hnyKrAw$ECq>i#A-`AAP~;zY}- z{ywQKvuA^BN?LUMBE&`pMi9M1<*dY>xutBrnzN##*DSFX_=hia*Z)mX-<~s>#@m*@nW>X!vw{1|$&>sib0*7W`})>P zMlGlenpAebe~UTWw7m55B7BDxJ>KY-C@33fzE!m|UlV=&_)f-UGV>dg4j(^XH0|K= zSHGgC-jr2St7{3n7ABbYWNpvGW18}zX2%{HR{vbS-iAT6MUwZyw#~~^KrUuJepX=F z3=j(fPJu*I7<{}PK=g$BH+L-YP@Zx7id{~1K7XhDpT8V`1us?~y>!y_iKayUbe`G# z54U#9t1mS9xlaF7!m}-9?JNImDgS@YLU(?_%_Q^i9t{(n-k+ZsQvUr-4T@>tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!4QnLz5J-*oR;=52M~@8CkGzsGH*A4bo*@OMsha+->Z{DB*4tPK244h-Ci^+2VQ zfEXNaKpGu@#KCd`wHLE>EQ~#x^cv;9uR1SsaYk1@Lr77`Wjndtwy+0tU>XZvbmsqv zW1STgV`X!C!mLSRrviFSDkEpI7yr2U$Z=gIP@T9(*$bF*Ca_z8>EV#|Ay1vD^Vfa+ zQ*}mc@-=hoenE$|M;yGrS$&@J%XwPnmV-V`jR6T}(qUIibd0vtU*VOVXuE}*-+iaP z);T$DMyMMcwrtwCQ?{e&g8QV0-4dVo$}nttaz>|ENv%udbnCZiJNLiL`M>8wOWFjF z2j$^+wVgIxcbc(yTK&B%!HSV5|1nKv2RaNKe&3n4Ju&p0bARRfP$eGr!nCrMh;5>O z^+Z@K#a|rA-K7K$KhYKmpnBx6LuNCC$WMJ?{?$jR_@`-C)Uhw7PydPQtWXG25*2GV z`p}XX1 zgxj9NTuMul7tImOak~0oNt@461_pHj24TMp2F9>Vko_P>zyL5$zXq~FVjKm<1y+V8 z2BuIxNC{Z&OWVukZvt#J!#V4c8F$!g+8&$y%xdYH<1+-FoWH*;;|5S2lVgZ)WDrOP z6r`WJmRvE5ue5jTuYA49Q5mIh&ve^E}i}1 z>lGSkV!SW4`1Ne%BWo5gJbxM!R>=EQ#iNIV*C&Z-$&6gPqWuT%U3%91TU3JQz{$R< zh+Rv~CMuN&Wy-_z#i?(sVcnu#ipA153&mglXY}^Eld{`w*@b(DH2n9pdQD|u;NHQ& ztkuTATp9>;14@`c-2|eTp=@3#%@o4@1k5CCK3Ex(nH?zWfz4+O4R&z`aX4h>Ic&*l zon$vZ>h!k-HCK=Cy~QEEf1Z`{iq`V`Mqch9H9$ZWJ6%IOz=o;)srpx@UTUVb`p+h# zDNS8g(d&O+KfO3>i)-I2g>Ay%G)gTyBb_3^c1}!lct7Rej=DXO2Vw*NooQ1#E>VBs z9E*ZZ^R%$S8_vhUihyAQi4O*cmKiQ{ULFfN8nCtYuesm8X&-Kx8AklQ#r~Ar+HKy+ zf6h0TB)Ve67K=dI>n zs<&_bWcvEL?`8Lc3h!Ua3jU5-1hJDDRxn|UcTk>UW)RKY19czaG8U-N+C>PMq`>9u zM3_DpjbsTD6DAAE!*Cuf%|Y!?S`_3Dm16|eWiWLF%YC3iYZpEV8oLP;R?zSobZ(<0 zye7fI8Ac;T91;^Iiz^NxVS?6f0+lJi^aZX{zy=VkbJsomVX=FYC{XbRV0M`Rw-w63 z;vf{i6Jh>?4=$%jF`ofBEfU=pKuW*Je!${>hEJmF9i=YwUXY1DGLPY3r-+o`+&>3B zIK-~<2d&x|W5)r}&-~&)5CGXQBN&0)Ur@7Q=@L|Tg8|`sl0jU?Z|VbRU6}#Y!~@j| zreKx;IY>;n3Xpxs08)2A;~AI+&Ojwm;)XakP5eP)H(|}kgT!r=gcqp2Lyb5Dm%B*$ z7#x-Un`SV^o-cJ+e~G!M{SI@S*z%Wpu9pno@@*~9O|PB@t>3tJK+`C^Edk{JgQf*u z9Bf$H6^5!~Af~;sIBkz7v`rHL)CZ~$;Q%SYA~E68xY91zexScMK~@BP7T^7-JU1!`gYPIKK~sd$?q=!DZ$p~Wwz2&Dgo z#5XbRBt$(%urCGc6C%}p@DvDSU`d!L;YXbLPb84*Rs!Z@O*=HOhZ28a1PhV?5)_rklVv_78lr|61eSRc= Nz-g^@C% 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 PpQsUs=;Z}G(m@OWU!ZU$ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410076 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410076 deleted file mode 100644 index cf94b43e9a064bb822a713af6e836a228a28053f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3876 zcmZQzfB^9wJ-f5^PpoAK;{NsYshFVHVF|w}QhODJf1dVJck8zWsuJGsw!JS`X_bfL z9k1g&BL3D_CZ0UjwA{3@Fh4EV-(+d+tab^T^5PHS|4&zX#9lYd3!Hd9bL;#G;d zySmxxZ8XTHq(#RcLTqGU1ko#0&Pwc=Tgv9EIV(DP%@XUwtMrXBEktd5^k;89o%_KU zsKnue`wE-u_p39#mC`a~vg?0-X_#UN_e)VtbOI5E#?2uS?JC$xS3=g-lJin)BE!iL(0FusX;LfT(YO< zB(^9!%)VB9GlRd}<>B?zXRDOD7EXQBRAM9&cyhApDdVeJ;ay4|kJ+OiZ-cmrfq_t5 z0o5@BF%w9AWW=vMHx66r=qYEW{G(eF)W*ERd<%Gr`Nd>Hth92mG2R|1tz z24Zl$0cmsq5(mo()LzWiu`u>%(rc9azUsWl#Ti}s3?W4!m+jc z4YST%=UJPlJeh3tZMXA(8%w*O-!+Sz1AgC52C5VHD0=}@&IEP~Fg>U{du(Aiel9r6 zqg{2v%i@F2lMd?1{%khmT3i3bw`kcSu1lQLm|4TtdHnD>ZL6u6U?x=7d@w1!?B*|# zed3xS{7^SITt9i?yRM?9*}VDh9#ret{cGUzw-4aM{&5FDzSK7o*`giyiRN8;%lG5DrZb<0MkG>K;7yPZ_4sQ z>%qy}dveSJ8~i>s}IwsTi(G?=1wxt8zjl&oaEJM!1ccNYDcnej+Usc?eJ zvgXgN&0hb4B9pm*<}uq%oIT@q7K@PCG?vwUFK7L~e$?}3VN>Gdtt)Jw6dvNXhuWF) z9|(YKxL<+Xe^5D4*fIml4^Z5L0TJQMz`p)%2{f#&fto;Z1P3rnfC5NNxHLE};XFtl zXMoucEPL-jwLC=TKIhD5(( z*pDQD#3aLQB)Um!WfLskG3-SWKw^^YCQx|@4=1AQT_inl8-WaL4%yBjYOb}rB8vYt z(`5O+!;i z5Nxxrdw6pB*+-&4+cp4G{RFtJPzDwUq4=E$^EbtZ{UXJDlzdEdUxI{u4D%xZB*Kox diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410077 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410077 deleted file mode 100644 index 3a04690232c4a82afa74aafdd64a9f988fa11bb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3700 zcmZQzfPmvCPD?6OygO+%0@4)r7!$_4N#*Ewa21wryUX0&+3)@v{PJ zZh%-2a0(=v!rhw{{^UOPW(sY8bAy7#QgMip+1_ljV zAR8QSAblW^wCE%skOGNu78Dm)85^6Jn}Q?|>cHw#`~#mdmB;ZNtM*jdaqp^U%KU)C z_x&tFtoBJv`Mj^$7pR^oAT%hz#}%v>Or)Q>mRvE5ue5jTuYA49Q5L1NduGa`HII84^8 zIPIf1g*{^y`|dY?0_HwBTDY)NvF4X^%#Jm&>tval6dopXfQ$v1*?DGzxBeSuow?4l zHcxpn+34GD=l?dAc0s>u7C8s}zMag#@8keX8!|wp$YFxaW^l7PX!zph-CZ-8ws+{V zo-4W3Z71Hb_|CVr5(#zgbCShC_Q;-11yLZt2sRg(<|6}KuYAvrJCthN)THX>wNvPa zzG0Z(v($&5#fx6pr=Kgl#=@z@eC_%<{_UrFXP%BTV+PqdC!3({$isC`C^AEcy0 z#)nDSitNunI)4*~cf! z;~L?&BtkVL$o|9cEw$eheq{AMEaNyZ>C&c4xrZ(X=q~iPe?8AbW;ZBZF)MAJCjMud z_pjM|Zq%mz(XHC{SbazMddro9e={bvSAWh2*$o6K|A7EV!@`~s$OV;IAOH#nW@tQt z1&B!R4D9RQ3P97m4Nwy+SR<5xSpwuDG2tq};ST3P@)-lneqj0c5N-^xT!E=0&P{LD z(AZ5Nx5L6~u(^#9R1T9FUZ8S|8gU4=AE^!lJE!^GhvMr=a>DPeGu8%5{b~QYT&UFi z$&*C4`H=hp Mw-Ly|<`9@X0MuV)mjD0& diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410078 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410078 deleted file mode 100644 index 72dd66b70905f66127d834cd482c9405bfc9fbf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5132 zcmZQzfB;`TVU=qPx0PAe*fsu4?pkp%EkgM3ouEBe?M_^53tsyXs7mm{4K;r21XFQLglQ)p1GxLzM8Y5qt`64KDl#E|muZ)#9X1DEXS zIf*UG4zsTn-^}1IcX@a{_1P+=u7y+IG?f^M1fHC%ddm2!R(O|^$7A;B$J-!oVqhQ? zS3q?vK+FVEf9e}+Shr}GVzKniLh+aX8NI#kr0jNEcH!P34gWo@UQ-zuxOXrxYqc>j zmj(fqgX0aP4-GIw`Mgk?DTMn8m`T`turekyyLu1Ee`Sh^Q@Ftw3gpD@^S~M0RpPn=^EkzHcahL)xR?JQZud9e>NFSY3j0y zUjOs@>BU)FT>D-rY!ki&RzxK`Bb_3^#!XCfct7Rej=DXO2Vw*NooQ1#E>VBs9E*ZZ z^R%$S8_vg}b}~ZZgTcXc%WdUFM)@7vr^s1dnR-0vkFxOLFHR~RJ z{B&(U*(7<>eqD>X8sF)K5zhNIxvMTbnD;RM7$}Uvaqnhx(D230ySrvGZST-!Jy&w6 z+fKY=@ttpLB@*h~=Ol|U@H;sG)4wcGJ#xGwvl&kOvT00SB)7%$Ws+2TP)H@~+ub`l z=3T$Y_bNmG$QAF?Ah$F9`p^KPfq)TgE-+vFPFIVW_aVq>Q~Gh6kP%Odo@#H+TFH@~*-JryUST5{s#*VUl(2KIyDYe(i8 z8x+q>V^Ph1rSdI>liOLT(?==KGwUzw-4aM{&5FDzSK7o*`giyiRN8;%lElikOn3U>X>q zZgt>RO1C;&`Nir;|E1Td#}=7+NiKibU#WF(qKc#C6r*qYIc7;P3?2K&l z8*B@X^X48}UdFI-(H^~{P+Nfdz-|DhgS7U4E{!H;yIKE~Z!v6GwmE%%mP}!gRq zKi4A3Kb2xpZyndZj6D{*Y}>K$JWkc)s;~C1y?FG-T?1YoG0SPJKoeQ&cP{?tc{}r# zW5PHK+bAK2S{*bcQ7T!Mq#4CRB|4+EeuV}_=6uow~kXOOy7 zA_LR|3PYHgF!PWFFyw%Wz;Ogu46+*pAbAZ`Pd+*G`S#%_Y8F;I97 zHn&j{Ug&W`ZXANc1g)(Di(il&vH6Smyah`jh&+az<|v6L+Jy=EX$RycWd9*^P{g6Z zg6;?8xIk``GW;sIwqQF?Yktj}tE<-k2opPN_;Rsx?&i4@PTtyl>&QnzsCg;>fdI)3 zj6m)`B)d?`5hCg*2KM!D)j{&wA z$stHglHCMKx8N`Y=_I&q+kJ}ZUmb!vjGq+pdYo-n z&H436Ufvm^pHT-|Z$RoFU>_2x-oV9%m5-7zHxSdGUYxdJBDBvQ2-L?3(+i@J+>gYB wtH6~8!S(~&G#8;NQSt?GZd#v8V>e+f69$RfC>cB016qf?*IS* diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410079 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410079 deleted file mode 100644 index ff584b34d8666c142fdbd6d1f84121697aa0b2fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4852 zcmZQzfPfH@p9>!tZH~ROxhj^?J3#(?LivZ1A9tSnT~(@|_c}ohs7lyZPgvy|!);}j zHFk|Zle<=2Op6fydnahmRl5@x+k)4AOp<=6%sNl}(HRGh=Hp%a_uSH0Fyl#d#+JQP zZ@&4Ze(xU0rldv3KS69{UBFrPPV$F0hq}ug38>!J#B#}| z8>qx#`{Clt;`>zpG!_OphkWFp|KDzP2G_0GQ=e5D9aKuRI+(J^_T8eaK<8Kf*V9GL z)!v!Az+B~Q>)GS#=RZDNQ2T{rZZ!M6+?uFOCG{PX41Np7JdoWatL3&gKi#5gx5W8X z6)JHmg?%dWOFy2HpImbNy_>iUSHb^_{ZqEFOyVxSpux-_+9J>UVB6;9DIga!A3rOw z;Q)vQ0jEHsDGWZ|4j_8M{hK?Mcqq@feZ?-PI-kE&{?A{Izk(O5k6t=y`b1MAe>%@> z{)bz;<<%FO{9LDhD&g6dvi6mKwv_)rXQ4a4;AWC}c#npOPVdi83@QKqrUu0{aLJyY zlh~r{F#B5Z%?$o>mxtF=pRH2rS~&GhQ;CsC;K|9Vr;M*^g?A}=JZ6u6yba;P3?2K&l8*B@X^X48}UdF)hVG$BUijnGi+S6NAD=q7N9<` z8-V^5x8hlDw{fa&yuaaf_Sued(|E=SSvO1=~4Rq@-UhXEC0C zv|!4A(FJRs3H4t8@1>|U`vS;7u=`W|1D`UL$MGGj_Eg$&@2Y3Y{D8yv{VYPP_DM|n zysz1pfw64?(AupGOy6~ZdSLMn(htnbC%AzW%N;*wF_Qy+_nut5D5+N^og-7MV%zdD z)BVz}8ZS4684f@-@bDpMAJmSQwwKG_1lVeZbJis@?y%RiJvRB7)zUS`X9zqwe}7rV z4WOA!jv<~dK|lr!q@TK$TrrEUw0G;Te7(t09B!vdEMAvq2v``e)0(;X+Gn6TiK3cY zFy)M3{{h2Nr&*SF;!U1MO)pk$-#h)x)Rt5!FB9Vj8VC+c!`F_?Gd3umnZ}};{YvFq3MaR-Qm2nn zo@d_4lcp1d4T0)X7zD&lGcah_1KDU{c~TN8##vBYU}bDOb`(+3{2~mIzV+WLfz_Ml(}ky`vb-GUB&lUL>;6T8V0+5Jz&t282dBZ|7yD3 z+M2uhOK$DDzhb7Ga(rvx%ef!^t~A;FZth=^9Zx5$$U4shG>^sATk%B7(HWjg`|cP@ zIB|yXT5NbI-*coV?xI=SmHM}Lpmu^wRv;S|CNLT#4GLRO84N0az<^+R1ysfK>q7&w z9;j9@g={!foDo#U!_*LIz6=TGgZu#V2QBTP#2*;Jf+T>%goP3$&BJ-1I06A^IHJ|_ zFu%(IRe;T+cAWsW8&OswyB8KFG_e<47h$)TA%D;DxPW+w26PWpIqV*N-dVz;~u6cvhqx6>1ikLQ0rOOt=bMX%uWf(0^~CDpA6mI5)k1LSr{! zO{0UvZIpzUJuu9v5r?W*fbdb0WC5@8kCXl~S08$_!G2u$k)x+vS^fU_6i!28=iwL(7-v@*_341#OrM@G= nUSPV0ry+DdlG{GO3=^dGG#PF}i4Pqs_5* zHdnH%tu0~cFtuRYfqmKbMuy7TcYo;I^kMb*MzS14YqfUrm@>?+VTa7D^ucob* zL}s?Yc0Q3yiI+X@KD%Vd!*am+CfmF2y*3TkH?!ZqdEr!FjBMg*^H-fk^$wCH=`1=^ z7WUq9X%9S^di7EBLp8boM=Vq>UTvHwwR-p4%agqHN*P336nGzO+q^sl~gB}`8(zR{N?y7c(MBErIV&lG$rz<^UUUd zxV2keeWA(Eb^50go^2^>U-@TC`Tuhky7LQeCYgu#Xqf2q{`|y{^6zhIP)q}t?CCj) zEy@nFuNB|S;4gQ1cs=#mDy6Q4Q{Oa|7>NX)oUD4v_^MWTmy*Y0_UOmkAZ}t{AQV?X zbu2*41X6GK+L3w22E{YeSX8rLseDV}UeNu=*7Lz^6>*aeT+BJ(YIcyXu)TKj83v zKZ_8neG*eX?`!r2YGDcp4GQpag=hwm>8GwGSIpuo?cMq-UvF|0huf(Vi`V5D0v5*W zv}P{8_8FvxDJcp>fdC`atqya!_4Wxpp8f6qhT}YqZmKNnyEgBf@a|rX+1}9grzUpz zXU!4%wEl`YQ_WGYz0N)S@d4LbnYmz%;22cQ~|K4QZN ztnQ`l@{tVO@3yzbj|S@0#DB0UzTwLXdaVeh^I>skO2ckgr!7L z%`KR6MrfQk2(V1mYTn&lv~kbYBhR0l=KSIrc|^)4%(Q1lVM&NXN4@!rVp;FoNmrU} zH>^GQUoE%A<(XU8ryE>PjVE@N&++5{8VC+cDXCC-!;(dJc3KzYJ?EbBVORB1c1E`O z4Ymcxd2>2B~Kt=oX+F>shD3 zYJmhJ*nPlq=+8QX9g7}EWZYA@m9r@JrKHf=m+n_37$<~^bj^Nyu(-8!*Lk!1MVZTz z_dcqPau&T^9h?#V^VZ2QmpYHcvfENzK(oMMapIRvWAY-oEuJrvq}qc*Dp}v|-qA7d z`bEB18Tv=Ac%O!bg&fFks3X8(QEKiKWMLUq5o}Ou>XZ{2k`ZQR7>Fe-+-wdSzPNdJ z*G#7E9lEUNN-lNViFYi%^KGp}LY@1ZWHFGru&^NL7NBC}umHOc7#7zL*BkwuzG_S5 z?kAHOr&g>N0|rx!WiSFZ4J;j#N_O5F93i@+D2`SnT-&7A9anP}|;e(Utj?;@3N|Db6nARmbdlO-=-66vM}8oLQ=z8oZOgQY=mK$GYu z2cRZu#GwMna-@6-;xb4uY*7l4b}*cAilyL(#>5ucO%t5EPW@B+%Gh>S>Bl8cup(gH zfhCRpg34i}QG$IP1_m*WMILs*Bnay7=mO2*g_;GXkP;>m6RrZioFc03AkIzhz)lNI g-Gnub4idMaq)`&x1nRR=BMucnv5cNZL1G{P0Q?W1ga7~l diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410081 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410081 deleted file mode 100644 index fbd441566ec2d9a2a39ae33b54a0c3ea46c341ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6180 zcmd5=2|ShQ8vo8Y5wgu#FOscfiLsm*4jqoQB(ii%x2#h-*&<77Ib(vTM2H zpwJN6m#ZwPu{AVVr_w}(dB4y1nZtFjQ;pxR=l473-Ja)t{^$QZ?{*+)PNXLc-&E#} zK8d)%lYrl9UfJ2MpKDf9RwJFHIFhN5KmuBPov(FCQx{`TR*J-5l}$EVzhNV#!s=Ta zk^@22rUw^YVk~trH~7Qk+MnB0q+e3}!+Z|0WOLt5PMOu0qPogbbYM@8DOJ;R9w8iD zX2>)M7hgTfx?S#yon20I>#&RJW-Yh!Sj0m3T+rxLk6XHIDV=CQ)9ssq^|uwNf)9!s~vB4s*hl4Nm+l4IQ@{ zi|1=GXdlVsBjr^x2~3nT3!-_%+ww^_l}u-hp1v1&TV$1j|S9Q z)4O`874;|G&9*=SA(C7@`9GyQ!-xr04ZL{7 z4)owTz3#&_+w@n>fe#PJAw-&-(B|E7kjKxUx83DMmeiT#i^HdURQWAy zV%FEHwaV{0BW3dIYP(EZ~EO^<9m>Rxf*)J6m12_MW7C#&|;0eUkO+ z=i-s-Z#Rs7Cnpc_=#!x}k|%-c1@J-Q2Fk?(_akGxCz`2>nrbGel!C;^vzqvu)#>x#RD+4dx2hJqp*Nn+2q#!J&HOBCKSGH1f{%(GuU-*AqkYvz+A?yWbQ5qi~AsE<&}_ zoY~hF6G&x&08R#7TnPe9d9|A(9pE{z;XsgieZs^pfp`_nJ&sB!1z2J<1j zNE>)H1SiuKa_ZW?o7`dz;KZ$sIL8|bPpx*lmr%X0PM!!S^KITfD%bw%_@j%#cM94`S#G~=z#T2;FzMqD z40=r?1$eW9xsczyY@BdmKLWRO2tTe2`v;$SaZITe1dUa{m{SDROU=9bnw$TjbWHTH zn752h$ZJ>QNB53zHIj%Y10C27v0c_5syCqX*l*ZEM{XDU_fELNEpj@QF)y@k=a1A&4p&qvB{uVR&OFEuj~(M0(#7M2B+B?U|H0PR!omS2M7XS;Bn3I8 zi07FOIEsYtv<_eyDJqP(*51rLcu={bWm_GxFA0Q*WBQA6G z8f}dkeG$-1f3s}AA#18fDYl=&=MXH|Zv?qMFEF13NFX>6>tSN82$^_u($MwNgV|vv<^;4E zs@UjU{N`J*Z&*X*UDl0^!!>WOioU14B8wM7kVO(UX@?%S{H^! zzpJr zT8_^7cTCy21D$69=S*S}TVYH~=I9rK?Q{5o--`?6(_*;fnFH@Z;7$_)?gMkO?7Q=3 z@4xrkP6`0++hEU$!tAh;0oz|)4Ce`R#I#dH?y+bE+3-WVRdp}_%Q6JF=Pky;QfJK!Iybg=N}z3siT5tF`qmH) zee;rm9sFOzyfENosLl_={uqU+vxZ4bVk?Yk$#wjNU|X<`KN6E32*}?NLrFNWi_eI;jCe6lR>ZF#F&2WB_KN_4zy1VY?x~0X diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410082 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410082 deleted file mode 100644 index 71ae40a074df6e2b389b7c4e4b7bf478c7134196..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4884 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 N`8jepZS8WC{U;MeVH*Gd diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410084 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410084 deleted file mode 100644 index 55e0a613568dd2f70608a15abfdb800c9903b283..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6220 zcmZQzfB6#6)DQVFOUWknhj39c2%2|m$b4%HLHD^UfuUTS!c$L0UriG|&kN)hfr*l6T z1C=ofanSLZ|+#)p*-XE6}z13eEv@PKYuy?3SO)}dg-L;6HSTy={&Rf zA8zfIS6^uIbDjRFglAjI+E@PBQvUy(h3@=}$n0Gx*D09$rs@JoG2U0A1=e(8MwBKvV!+AV2^-WT~xE^8qa^H0NqfI(FCEF*Oqyp7| z^nvvfv=6H8rS0YNHvzVq;hc5Jj63W#ZI4ZUX0>$9@fiY7&fi~_aRX=`lVgadUl5Q1 z1L>!(C0ESiEA8F-D_?JN6o=cX5{uX683Go@>$GMrzV;cUj?qvTrkoM%KVTY*Xp4(& zSi5;DllU!8*8<^}`&Ym4xL5wa#>VT^+y(J`*F^7##|idJ&a>ovR{rG9jw=^maU>)x z*rBig_I&@h87J6)27<$K-@T>X4^N&jXg1(J_Dl20)P48mwT(Vy1x>cs;9-y2W5B@g zc~(d-RS%Z2{^7y8-Cm!Ue1HRwWzPi&oD6U+nLgm9AA%h?}jNe7wxc z(mnes<_UTjd;_Wz_b7V-Q_ci-3(()zzBk)0{7d8ExnnL>AU%1Pca7ZY+f|0z>zIt2 zMMWAi{`QCFiuSj1HRK7D%#CgQUR1s3>7^LO{XMytX1?4Y#sYPNgV5xd&gNw=ex~|z zguQ)ix#^zkhr5n>-Chil+!cl~)mvWigx2lc`~E813uTq$qKVC&i5CS!Rb`bDoxYlF zY2@YxIt(0shOZr&XKYYBGmS+x`<2SK6i#kurA{BEJkPw7Cru{^8v@m(FbIg9W?;~8 z0kToTFKN+96Q~$xL2-eVv9YlUNB}AZr->*tm;yqB0(@M-dcg!SWdXCh^#Q03MyOjI zn2%%|`yGw!Q<3bGpU8HZ<9fz}`0wB1zo{OXZK&ZpWx}!&HtuxI`+I!N7DuL?=(Aqy zf9Gnq`3K$unROXYy#jfF=CSI$JwDBAuU%MNt?OJDeT6?Zhg&2QjGqVCwJGPTL~Lz` z+L`hn2!L!@m@opl|DbZ9uw@386`;HW21JB21N-_{A<(b}6%e2@9u8oZ00oekaA|N{ z!g(OOK>%t$u$%|w7Z6|s)rSx!0|RkxdijCIZUVU-7G8tRZIpx;D8Eo64#8o9)b;{L z-~Xs@rr*qOrS>uHS@-vFhVS8P?KL6(J{xs*9!xAgZTcP>$0<-6SDFE)(cEKDH4FsH zQlLVsN%orL5h1j38D5x1KhZ5#Qy2+2mZo-;I2Z`G# z2`^Bchysuz4v7g@f~%ZCPop5cpfU(l1}edH6Rca;J#0RgsU-?jzX4cOO@Qfx(O4XW z;&&p<&uRVSM2h*KG8F7LkQ<1u^O5wx+zz6#xS!$be8KE*C0!fO8XJ3vG)`e#*U%(Y ze^lqplh$B8H;zMBp!(7CF{m901F*7F874qPJCs4{Qi%*SZZMpMB!I+(nT{(TL+UzQ zbq#TDD&9e3H(|}kgT!qpX_-Vfq328Fv_?uC;>yRcd;m6!2)7a6$AKj)L|+Hly`b^~ zp8trj7nrW$X^3`VLYbS8{YR~MV)(X3#YDvSQI2cS(u(%QZ@Lcm&PSfry1qdHV=fa z%)2+UV6x0#sD5ny$X`%7j66w1Us_CKk=r_;i$G(3p#D2-%oc1Uk~@)@P}`tm0&pI@ pjgG%=C(=#8acG*l32WXTByK|~FGzF~Xxx?>afn{GBSkX<0{}zyZ?pga diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410085 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410085 deleted file mode 100644 index c5b81a78f23c3dd0e4be063d4d63ae7c68db8ee6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5972 zcmZQzfPjqSYs(n^ZIk!ywP|^gnDJgI>}|%?&qWXKAH8ps8RB;qs7jbyH-l#z$J&Jl zrgSdo)-i2)SsuIasL-Na2RZI8sxMFXdi3(;kyo{kORnx+k*E1Uq^NdZ)u)!$SxMg( zao3&R)w2O)Q_`XnLJ%7n7(w*bSb3?9`f%%nll|(#CFtlkLXZ&kF3R z0I?w86i76M!N=PHL{GSXbH@@7-0}0Jlj&%zVgqO^8e>7bmte`OfnDe(J;~J{rQO@<=@}bpqK_O+0%0p zTa+DUUn{R5r838enZrqG=si-fs9T;0H-6r9T>ziQT^;|)F1J^L!=33?cOW0*0m0T>1BQy0R5i*tbZUM%w40)+YhF8ffFf99&`x!<1xqJ%$8T$!*+=hV!aiHa~i zVDo`-T(an<8*5Tb=;U*bAsRe+SqhO4%lai>)h)3wdCPEo|*b4DPLTVuzk62I{ncm zot%>G6HQW~`oMY#+6T4crS0YNHvzVq;hc5Jj63W#ZI4ZUX0>$9@fiY7&fi~_aRX>3 zlVgadUl5Q11L>!(C0ESiEA8F-D_?JN6o=cX5{uX683Go@>$GMrzV;cUj?oYn{0xj> z{{h4D?QNl^bBj){y%hWCtDmi<)~vi;C%>6X1-rdVyOMJ^Lbtze@vFVbye?^bVrv;D z71*qm2&?LBxy~t9IyrUXq1C)VW5HoL?O9h-#bcf=$tuo;mu+JU#5%Mic@1n?G#h8t z35OKwG4MM%0Mmss$QeKk0w7u<(%8SuKQqJ0FFQE0BFMl!O+To@(9zZwDi2e~uQ8|oARSQpoj-(7C0;feoU7(GGo*@yP#H)Ni*+m`A&m1io3(Rj_f^I z`Q}HBHBwlB)k7Tu3J-AD5Y*4Wzy?wa^RIZ$jQH<=wO9O>jEntjRv*C?{qb5%^joWG z$MT(cypkdqHZIzucNA(1P#@S0K>rH7eORmRXTi1Tz{j(S2NP~wJ(=6J)mTUJv;TRm zKPP=RoqXnEc`&ZaHumd^MRn(#HrWO`l?50ysCF@i*!?`#4>Az!e#6&}%riD9o|(p? zn*B=UTM8$)vr?yzQl4kt$&;oNgbjh}QWylpPBSoQxB}U*_y_3+mI)^OU~$b^c)X(I9tQ$T1?fDgz9C?F%%sjXyKmnM2a5*3YIW2<3nZc5fvK&-)gYr5EFaph2g)kWyh;vi% z4jQ`&nCIbT^%4-Jp^)Ej_%WM~*CRV6cFoon%Bqm%1di=oB8Q6YYY=flKyHVH7d(9q61Sn0BP6=X73eQŝLkjfEoq_@o6y>4b<(M|30a|ItvX3nt9 zNGMpH+W-5XNloBqo@2P`I^?ti3v*>yDk7#0$Mow1sILLn1Jetlkqw86ql6!k=ELez zWTU}sEaqcPJ2bF|5`SPg8%Y3(3HL6@Psjk4m(kM!NG~i7LHQhP7PZ^#V25C@Phep} z6MMmZ1?=`REY9D^Gj~G9R^D5e;++%rJqai~V$vr6L;J>qYkRJ|DEkf#yc8%63uAD< z7bqs~QTBWeR1P`(z(NH3+F<=J7=U>IT(&~Zfm1Nc-~ym{L8{}3Gau+a;?2jJ2WVgq zCH}w&79;^ACOp(g$pb7vT_|lE68(;0Kav0vlVrES{Xm3!K<<}<*+6J)hG*ICt8?0y zF9)gzjoD$i5kmki4H9AgnUM#=BXb!Bu1U3>W9FUk$+sN#D5$7h? gXEb&b);vE*+=fz4kmx4Rm>)Ib5WTL1M>>cB01P2%U;qFB diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410086 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410086 deleted file mode 100644 index 53663361c20d6d1e8990f9089f3cb0830aa0b0bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4528 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410088 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410088 deleted file mode 100644 index 388d4569e7bdcf1d7690ffaa5cc12dd719c1a05f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4048 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 NI7F{o;gJqv0070G+ob>i diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410090 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410090 deleted file mode 100644 index 86779c9e3ae619f3e76c48d1e787c73560e13054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3696 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410093 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410093 deleted file mode 100644 index 0fd9c17e7b7113142fbd46186fdce5c7d00c9314..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4696 zcmZQzfPiCnHK)B5a5%VC%`xlr1ePmPdlWP-tL?h8vhTs<4^4*zfvSWvT5UtS-!~Y2 ze*euTmvb3scF5$ul$EV__Zf->E$Te8j{B(HjrgxAA5TYL>p$7<$0R>z&7&v#gfG;k z3jJbk$lnICDQVFOD~OE@j39c2%2|m$b4%HLHD^UfuUTS!c$L0UriG|&kN)hfr*l6T z1C=;1i&#cYU|hqxq|-le!7Jf;X>Wu#h6H>rnsBkXU3~jR_AAZV6+u&fNE~L$S({NY z=|Q6Xt=NQq;ZJ?*)Kd4A(ob`B{1|)7*Qv?%Mu|YA8_L+jfybv_+Tq!M4rIQ$Q|eK7Q8U z{tt)+0jEHsDGWZ|4j_8M{hK?Mcqq@feZ?-PI-kE&{?A{Izk(O5k6t=y`b1MAe>%@> z{)bz;<<%FO{9LDhD&g6dvi6mKwv_)rXQ4a4;AWC}c#npOPVdi83@QKqrUu0{aLJyY zlh~r{F#B5Z%?$o>mxtF=pRH2rS~&GhQ;CsC;K|9Vr;M*^g?A}=JZ6u63=U(Ey9mV< zPzf^-GlA5)EMt#aUL$m{fpzJe4DXuv&sFy;JY|zP_Q>V)w=6c_iwwHQ4gkYI3#J}O zgW^u2G&{M{!pOKHBGlhY+odAc$<@ctB+%9tClEA$8n_)C z-XOPw!xfme`;yYu6zr5$k|;WJ&Up3>#@0U>!Z%zuKHR}=b3NBWV?s(J*N3`3j<9sD zk1tFu*cCqS{Q0!XXyWvj=8uY=cisk>2R1XUCo1fcR(Z&WZx8l8m8!{^ekG2fWv=li zmK)4_^_3YC82FtW(Bcs0PjGk=)X%`c268tv4j3AFj|ks;%jwtn_lk9}hQv(g38o3` zep?N4GPj;-3Q~E_uyN5Iy`vy2z`i*_n+sNaCKnyDgJ>^nabn%j#Yaq?YMW3?kD{T}!T*#aG(9^;f>$5db# zo}G2d5a^EB+L#gCE>(L;C;l@izcCBXU6lK0dbps(kJO*nUwc)>GCuWYTO8BJ?Nevg z8}0xrv%sYo$Zn7WfB+P)FaQc$W?(weh6xanE*PW^8^O{R%uJYexFtXV3^||}I4{@G%zj{9VE~n51d71}jW{2R4g{xFo*J0UHh^5M>VwObAGW(lxp9M7uDd%uOiqfy6;#!b1Sv z56E$W+%99VSRugYR*;~yEv2yQWuv)EC~IE%(;TJMOT4=}f*kzTLri4Uftn042U?Fq z#gOd>*Y8kqSbl+*FGSR_3{0=rVJly_L1rRZgv5l}MrQd!oSW8)U@2dy=_XKE!NLok zZU>3mP|6n)-GrPDDG4w1@&%L*Vc`Wzo8a_7?e-x!WnnL0U|~WJds)HmfDkZ0!^>0} z`x)78n)(^s7Dt3Nvb{9-GakF?>1X7&8N;p>Dye5vgqC*PpQN_#^D~~ssjWw^Y+Tp% z>)i1NTyq}ZhNg*>|3Cm_!^%TOAom|s4i;`|P(A|@?Pvz}^)EG`ZD}{4KIC|STY_XC z%xDk|vJV-+>Kw5Bz_x)nR1y}ZU@mcPdU1rtZUVU-7GCi3caXS^lJElcho}*U=;bdo HDj^gA@L7$r diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410094 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410094 deleted file mode 100644 index 7e05d0f9bb48272b1414932159b8cabcdcbc6645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4628 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410096 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410096 deleted file mode 100644 index 1ce5bdbd0597e9d1068a26b0fbf033aea0d65cee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7196 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410097 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410097 deleted file mode 100644 index 36c7b0d4e761c76a35574fde0f04d8c00b2e4390..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6016 zcmZQzfPhEc2;LDP?hjR?dK(j989b3 zeY&2i;`y1cx8Y#zmg@T7XSY=0W0^V54TP@$sgVv>MnC6pn6{u%O#s` zpc02iLi$1Owvll=U+456yAaU-bSJ~B8!K+<1?~CAKQ(oShGFuW)R3p?5s~eolH!$; zm)~%OhD0|%7s}P}+?N*gfHQXThOV0p%RjBiS2=KwEx$AWV27C0?kOLZZ4+CxOyw-U z|NSX@ygQwi%I}zr>0<`b7DL_#+cqyx0lAp@_*s81 z6%Y#oPJu*I7<{}PK=g$BH+L-YP@Zx7id{~1K7XhDpT8V`1us?~y>!y_iKayUbe`G# z54U#9t1mS9xlaF7!m}-9?JNImDgS@YLU(?_%_Q^i9t{(n-k+ZsQvUr-4T@>tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!4QnLz4wp4n9WShRFi@28#qms93RTQJ4X3pfAV;CcMo-`FXCLK*m-92mG2>w!uq z12H(>fHXP)iG$??YA%3*&=4r;=2C8cfk4?{+|E>MTJ=Pk->ARih0o93nl)Zo{X9Bwgm>&8cb^q4lxccz( ze)(kwUo2Xhry|yxH0xO0w{5Z)rk)f3mMe4idOXvY{tw&ctz{19eDwdAXqt4+#3Mhe zDpK?`kMKa<;GoW3aDXLJO7V-aP4fQv*0!M|7yQ@fer(QUy6U=Q>OAbzGKy%N;~dd^-P%`aQMET zMTpfti7B7=HTyC!wk-e#%~l4c@1{UKDB%ap4_QDlmOFmVVkQUt?mfA9QBto;I!C5h z#kS>Rru(H`HC}ECGaR7$z8GwGSIpuo?cMq-UvF|0huf(Vi`V5D0v5*Wv}P{8_8F*7 zqNwH;OgSUif513-yi}-V^Ph1rSdI>liOLT z(?==KGwtGFuna&eT6WIN>8subdJ<}AV@|?jI7=)rN+CcTpFh>AsP#y<|5kdXH@*Si$*wq=V zoe1>|X+2S4m$b@5K74zy@2ONx&h#sB3@vkwH?iDc-m9<7kN`4B{CW$BBGwJ;AjLbT z%FW1I>9=9+8Y#JDUz=*U59?mp&MC0ctRUs)uQJnoka`5U!AVozJ~ZhoLyEDH|2n`1voBBG*E?^lraqO@5H#Vgm@%WB(Yrq^plplKB5 zcaU~&5P@V75)&i?2FU6`0+2KgwI5i9I)GJyi~-iwP&ScnTHQipH-X#^3$MZEHcG+^ zxtyUS4#8o9)GmazOJL~>oF0fMYhYypQSoj)>l6dS#zlMdj)GGQ8!XKLX;_%h#9rmY zZn*4)r4a+L8-N70%QL7SVQnfU&j&{@3&(OL97S?q2 zGakF?>1X6T#qdACRVuL}s=(KxYtpVyxu&XS*9>@;tn2%>f=)*4zZ@uglCuA7arxF=zrw|>(z}~ z)9UL_`?1_e>#NYY_SbM9M>8}rq(Et0X$IJ~%H0oDLwNiLsL)#CgBWxSXc9~xj7G8q zi3yVh$1$7(WI)p>#Qvm3LGe&YlrSeaCI!@FE%AO6jopMbjSdpGQ4(IDaXb`&6mdvQ zxDs6D40;*`=>^3vsO=6f0||}?u6yu9dj2j^puP>jGG_wZRwx6DgHZfVg!vCHYg{75 Xe9%}5yi6i`oDxY7vLCRxA1)0585Z8r diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410098 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410098 deleted file mode 100644 index a05bdbacfc141b2dd8172dfcb8c94dbbe8343527..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7080 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410100 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410100 deleted file mode 100644 index f4be81c033177eec4bdaad32f43a1882c05a96a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4844 zcmZQzfPgesonKyR+YG(3_&UB=iJUsRc-mTLm+NoY4#t^od(N2$R3-e~)O^xov-z)c zn)WuxS6y~mrPmwHWOzLFe$|#`pZ|GUPukY{=bG51k1Kuz3m0+=Iah2-dT6!1=6YQ3 zy6|`N{wxC7l(gtXJj6x@Mi9L4_bmwQaU2WOW`cUQK%tAf?`#d_+l-t}oc*L)_^gX$M zzPx59$K~HI+h^%=Zd)_&>PIe7nNEA|Ys+J}XF7>@h%MA#vZTLX@@?6LWvStdS4nm2 zZS!<3o&NUAf=PR}-Z8P$+0t=XtcZwC-f$gJr+v-uxx?Uq+xX!3KN{;7m#Tguv3{@GIg|D1*H{DPZF z=HWdWCOW-8KQW~I`iwErpZYS*g=U zDbF+SXRNKe zEWXm-t-td1CP#6&ohq?-U7jIeVZ2Uj=HhFg!HQ-~Yk=xtgu2yXcHo?+4t1Ty67w@> zcz;_txq?aL5^L4&^%d58R%=e5u%g5#_2U&ux0?KJJD#Ka7L~MAp1r8Pk2}1`Tv;sD z{UAJCY~qyzA1pj(tTWG@N&TJn3FfD*Pfg3&&g2O!y!%nbt&@S@$pM%)jDhwehY2#9 zAz>2#t1Ifo-P`3hIM@{Qdi%~V;*XA-$+>dL+*twIIh#RlXZrP_0Yn1-=*L0W1ROAg}7Z&{Byn? z+x10szWs;hKR&a&Ie}(@aLmK{jTD_(+ zFmUf+VAg75U@i><*$;9A7QhS@2>EOv2`al`)yw)q@xy^BF^fU7SH24%vAQ zTe4aw+0BnS{cS{*|ehnrW^6 zv&m>mQXa6S&TlMxah3=X|foX^%r9(jDkVB+~nXYOlXoS||=i7$lLecQCd zAJf9^RVJ=KpsjK{VP(w6TkBRmGMY5?wON#x@ifopZVf31MEQW`f#beayoFKyy+r({ z8G3wQ@3M65_shJJnwgYA=SHA%w2X18>gdmxV0MB+m*B5Dx^$$m>0my+H)f2(|bwg=GLfX z4V!mw;FdFe_M&?vsSq#<5^it1#yT2 z7# z!Drst=KB*59Xn?9;F(j?LH8wHPYO2t`lPud*Iy4B$Dp6n&Hf`3PN+|m^mc=lktxvf9%dIKQW*~mZ+M;|qV3DTzW!MbwEYWe zry}P;c*X>Z!|a2549LJ0-eCKIX(0-#7$toY=_U>uy9wlWSa`wH=OA$#CE*3?!%!m* zv6kz5@@u)5Z@C;Y`wkm}$enFAb&uNVj}}1h`w5sc{3^CyJs%@>_;z5h0Nane{p$^9^3xa8=d6E|D?+R zl{ge6F8FruXZzD6rZeX1iL8H{V)Nx1E?f;pX>~iMgXZ-^w zK>YxuPJu*I7<{}PK=d|G*V5^4zbu%vXX_mkJDn{J2mk5JRAW8)`OD>~R>r7H(|Km| zKit|aufEXa=Q{mU3D35awXgiMrTqUn3*GqzH_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ9q4G0in18 zDq;p=CXiyo*N)6HHYlE%#-f`2O66M$C%3awr;k#eXWq$^rW1q>fl5*s1jJ4=FlhJ# z+2D8s=>vhJMJKy~6iAG-pt!)w*x1Ct6eNLA2UefrANZ81JdW>JwWrdKdsjVE<_8?U z?`IKWwNGNo=Y7q-K=n)kp+NyYu3)`jBK_30L%_m# zoz~37*FJ+3v3`9B)4&LIt3!TK_wn*8$DZpNJKg&m(!$ocUoE*`mCr1y#D0O9M#-@U z0S`{?cI~M}D&E4V{$3*f(+oYnuXkCx_WNaLOfoc? ztdy8iJB!_ZI>W|Ad-RS%Z2{^7y8-CmQjya!C*lKUMy^($T=<&n(tP&mtm(bWv zAh*N9Yp}VElJEkRfz*gYaF`&~hv4Wto^2mId+WhJvue!5D%rQ~pL8kB!}F9?W*fbdb1>lJElg3k4uW91;_*1YJF>oIy{cAic|no;{(}VaC;d^0EtPmo8TG%RgQh6 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410102 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410102 deleted file mode 100644 index c56cfdd6ad3eebfc6643b7ee7ef46e83214fda69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5768 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410103 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410103 deleted file mode 100644 index fe975c297124754068505a57ebe9276723b532b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5580 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 QKmwkUIK-Ncq4CK8019JomH+?% diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410105 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410105 deleted file mode 100644 index 8362ded3c74037907fbdd4e6fb742064ecab5181..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4984 zcmZQzfPk$JbC0XqWG(s_uRN#gsmI*=W-UGXVRN!X4)Pg2j^lg`R3+S=YtpH1T6<^N zw^d&*vgoch^YUkVrvBnxyq8GIBa0VIUp}iCw7g8zdFrBg)~cqrrg!Pw?5U^4mvP$Z zt+;DcunJ^T(xMYp5E~g7LG;z4%$rF8-#v5LXFqyjDrENl|BK6W^w{>V-smJR{wG}q zsKkNUVb%@pIa}K&)=aA^o8~gVJ2R+H#j@huw=CC=DHezQD$j*HX|du+wZ7m#catM) z*W_=lU6W5utKZ$4)1H3iF;_?GV;@;v4HMHT-c3x254TtIoO1r~CQfTx>xGL;d>Yp+ zR=E6%Gr`i~9@94Y#Rum7xXK{fV#)hp+vepdAQv+qKkFX@ zau*bw0*R(D_;@>j=xv^^rPJSjSuknO);lJ4I$IhJ{?nPM#(MJem&;MDj8T`S^UUUd zxV2keeWA(Eb^50go^2^>U-@TC`Tuhky7LQeCYgu#Xqf2q{`|y{^6zhIP)q}t?CCj) zEy@nFuNB|S;4gQ1cs=#mDy6Q4Q{Oa|7>NX)oUD4v_^MWTmy*Y0_UOmkppIf76jwlX zEI`ZzQlBu1|J4=s;_mHo8ysv3dcA$;7x72O&E#CUWbUj0?VQaFwww&WFfaisWd^B- z0+4=i91_$IOgkX8!LH6=twgA2u!&a=e6aACvCceqCiQpPCzzkMJ~b_8JCi4{@a{(y zw@#2j;@4Y16tQk#2Pv+%+SGct*oP~1LGVh^4eR6U_T7DS>-9wMf6GpKvUNOK0WuHj zPO!N!^GVQ0I6Q%d(%9|bcm=r~9Dl$(l(cAX=IyYFtXdm(xGU6eTG5|-_*?d__=>42 zFY0ZiU-+)`^jEEUx7N5ipp3b$Dyc6>=HuevBi#k&S51zTYVTwNnguq~=FX8P-2ZrY z7@c}FZ@xm>qIZ>w`C&7TM=!8AU328FVGaYolLG^{A}Fs<2H6k9*Z@czEGJNVFsD$Rc*^cgxU}o9Qu@@duY8@~ zmv=ZM%h$mPTZsH1xz^;*eyVR*X33o)DTqz{Rx<0`4 z>iGyywzsFE{9^nrxp%B7NDph(WZI;`-uo7*dG>1CA^O?BQbB@RY=U%@pQxi#OWJ&nGBBtMFbMl) zFffJ{0rjASAF%9%g(*itaeumlP~#o%;`f8bN5 z@;JU@)t*W_?p^gvnICZYzMn;i)jo+SpZ7KU0u?d^ga!rpxPr7m05RdhFk@N+R5>Hm ztqyZ$UO&3%&H{$5c5!iW%qQlCPA%VQV^Wux_$PLoQc`}}4VOtNi=R9$vS8>ased-X zxcTXx1<_N4Zy&oVxqY?O6fU57Ea7sAMPVH3vwN9W-tCk3src8y?w{>`yluwYwbyu~ z9QH%)O!*H4KsGE)7=he>P&rW8G6TzP3n-s~h;U|LU;m^68rGmB!V1$1qG6VxGT|z~ zaS7+a>I$g+z_eQem16|er!aLyx=Dn_ZUVU-7G8tRZIpx;D8Eo64#8o9)OG_$U$~6* z#g$0~e@rKB@eDU@-zoU5;~OV7RDeq}K6bR0Liwe+3SnDHbd@=w4 D6+gw9 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410106 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410106 deleted file mode 100644 index 4006a603f1e97908f69b71b22a9bafd090578a83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5080 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410108 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410108 deleted file mode 100644 index 16f2f5f6da07622db56ca83939c1d46fa8d10770..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2968 zcmZQzfPmwnT-Mi)+N~?io&59%i|F4oWp381oFDt%4x0HV%j~EvP?fN)Se1VK&C^rl z?2qIa&ra7d&Nx!TXZTd+#yRhePs-%~oL;BfBlJA5e!?el7tZioQaZ)AudZ1barE6h zmfv35XN^HNB`rG939*rZ5kzl|71*@9R>SY=0W0^V54TP@$sgVv>MnC6pn6{u%O#s` zpc04B2(F1IWtG4620uIM<>>RIF6qaXx3g2XU75$n{!A>mk4LYkaFa4yxa*9vr>5N& zb8`A#8oHeOvrl-1S>?$&%q)gNt0wzs2L&c?cZ?DzdF*H3rcZ8{P-oHZM;BxtRI*+1dNf zfLIW43M87s;N$H8qPKavmQH{BWx=F9Tkn|I>1=5@_)ll18tci=UoJ^@S!s*Xf^1c($diedV7m<^RuF=*};=nPeW`qhX@c`|}e+%D=y0QcS|5^U9zMD1YE9nubBmW3UN3XWm;9NOWE6Y1JcLxOzzFMBkVc0!QX5xwP{U0|hm?bBf znD;PqUkcA^+jqBuRbPJI333C-9}NA9HNrRIf^s(0*h~Jak~*K+`6(g9Aw-DZn}3h| z)`#byez1b62k8LMVeJi(_mh9tbMbF{eCW)*jo~qS>XZ8G z<2Ub{dZI^5@QXe3uQQKkbU!-$?81>Uwcn_R<6E{aW%r0+_+Jg5nGUVDSWUKMa7vj2RlIU@;>6&meW! z2$T*$VF)u5W*)Kth8$24IF8_oL3V=xBu#+ z1QcF_&25x~7kZqK8;9U9K`Yl`@e7h8Hh&SHw_phbk;jnJ93}BYyD%X??SR~b>_21< zia0b_(EWfM7s&N5!||ek>s+@Y&f1IF6-q3ax=z_^J@2k=d++DFCLf=)!1NK=Jj`+g z7WyC>WEV;~La;6YYLGpf3eWo>Ly!R$522)SqRii?bO2ViAe#+hV=*7(2be$L`I`pz zP~r~^XCnz9G2y-i`3D)`N&_IhAUTvgL!#d?>_-wnV#1w6yxWlS3^8tk)=%i|6tKle d4nbm)>?TmUg{Kjs+dN2m;5Gso*c<|r2LP<3&qV+L diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410109 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410109 deleted file mode 100644 index 20e756d66d12a96eb7c3a23ec5503d5c58375003..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5084 zcmd5=3p7<(7(N$Kl55;libN@Sl*CnWb%jJ}J;f{sdUSBPjQ4qrSU-^!tC*_3A?oanZCPnbB$Y{ zWZ0vFep4B=yAQJ(e)Z3`p4dPOROoWuGd0ep_prc^qU5faN7vMtl2pq#wq+MH)2O`X zaXmd&i|XpK?mjfV8Tw*Oa+$(-DH+Y&g|)stlGAwMn|3x*oF(mZ`gN0594|3yY!T~7 z_T00LlUlcU?MB`hL?MbX;d#O3Q(h3U_?`P{C9aSXjxxygLRPJ0!nwf8f_0>|BlA!Z zzfRvoJD+`{Pdjz?n9_G051pea&Xq@G(x?LdL6tdK`XBS=mwCL(4~{w0lONJwu}CK) z;IXHnQ=EprcKpY7#H+8@+s>6Ot$Z(iL)1)WTJ?^{o2en@f*S8vxoWXlhu=o*)SI}b zl&fC0uu9V@R&7P2luKiQ5EFt7mn$GA0e)gozPZJ?HSvVp`mL+|I}=mnI$E55nDw|< z!kSlU`U=S_ut!po*&qf+KosT-%^TbY2gv6sAw}@V!nL)8N`Wnn+IzAsXnT2;K}C1F ztuw8SbH*cAyDT-7qe|?7`azB-ols}SW<(~$%Zu-Q8D!^ni2w9*x6TaNr4>uGw0)+B zDNEKx?G!ILKaW2DnGE8SHkS3`_~wZZWINMJI2k-kX`lo34F&9;rHH%oJ?Lj4OX zvQGup1e?iW<-AU{fa?##Yp-825kHSyJYF>KHf9CvLoon<_dW2}vC%7P*dM5Mv{PA3 zE$-q{!`-|E=lhQp>@dIR8bqz9PhY5+ahda!`#wtW(URWUez<7C7T*BfCYN;e_fkM3 zihn`Nc=e>*apRDnAf#5iEM(S&Ch>&KX-RI*I}-cY`Q9Xd@w~x#$~rS!-CY(IA@r?I zyX-CK2D&~@7JeZN26#r6LlRU&X|?Wl+b)DIRqWe6_0KH_+C3bY4)WBM)FKtWpaRO{ zu^1K$5H{kKfxqaWp!h&6bedZHl#a#POpJ+H>M>zo{W@kFyMdwRaxSQvZLso&!Nz8< z_}Fagyl3GYv3Ns&9`bkdblsG~P5NS8l?@zeh!>4TfCeYp&A$I+rlORYWCu&#=z*$h zY~*u!w`nQmt*dVb13B=nt}R6n)kA>B{Y1flI?hFjPy7i`#&M;PJ665<3R_XxgHKbE z3zrRE#gsQ$G?SrMZxdG=f340?2S^p0zgDn>(jwrX*jk{XNV%1~kFf&BuZQo9oDEtw z_b;W~4I6(d@r`w8jxk=g|AWvviWT}e5m5DboI$BkLG_Hp87PZ*@ex% z)$X?3+W(Ph=}Vf0spBzgt{^%+yX#c{wn56>Ey!!PxHkbM$^L=tdB#YV`9kaLJ%54SMf`6hF+NJ57dTo2?g zfZrgDgBVbT6dw`vPh-7x-!lUJNH=TI<3u?X-i+eS(gKd*g(c7Q4Z1QTvN~PPy>iZG z&Bc5h_)fy}4j*_88{-TS&P!zKO+Ea~9ppBNK_YSO!oE(dU=6{c5QW+YHFf}d_F3#i z!?d6d=)vzam>S_k0zx7Q5u#==&i`S8a(KLmy8lkFeNDUu`cE$Ik;Ds)$$&nA#}Yn6 zb%_u!;{Gx0T?|j*r#l%L?`Qo<1iPTFi5eQcn2>tH7hod$_pS1T#Qe^u6~Eb3Am$p_ z&23wCGNY*Vv_phf+>dgnZFBZ1ti!_W)ei=qM=(zS%RcNG{$3FMRD?Uz>+kPBv$xdte=A#bR^V};w>7cu*^}$1Y?EAi|8ZY3AWGr$OtjP zJNUQA;lMtErt*0}Kt^G8OyEANbhB&;0i$FLmn)fa9_iDI%{SFDJ&FpU-vcOx*9<;G zCLVKmMxaBK?;EkMHa2#y;M<6qtQ=#07C#a7D~&+^khL=kcD}}sL17^=NF)(P=o5L6 l&y0cpU&3<;?+d7|Z~Z-s0vY-|!DBKicG2(Xq3sf}`49dG=CuF- diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410110 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410110 deleted file mode 100644 index e9ded78c9b1d6706db1aaa168a5b015bedccb3c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2740 zcmZQzfB>nJG83wvY8m@PJ$(N(^M;*3qwB?I8?&vmKU{ps5a9I{%yW^oDE$f?fuaAZezkB$h#Z9~U zlcB#!aSzC*q(vvDKx|}S1ko#0&Pwc=Tgv9EIV(DP%@XUwtMrXBEktd5^k;89o%_KU zsKnvYFP~XFs@l5*+O4NPQB&>6|3C3+piw)^Sy`vGOQy`=5SC6pccAiT$|>FX5{>My z*LU6aeU-~OZI*<4`|QNqTKsPe_J--l_T9dDc7ulrbLYuZPFIw@wEnX%*WIw7-}>s2 z`yV~>vl5@Tp69dm*xMTY)Wzee!Q>+cmDu|=tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!GW8Tu7#gm1(Jn>9)2|d6+r|!SADX~$-6aF=9Nd>77c6A1+Cq^xU`1KaBS|Gs)b{{Z}Ea%|7q;YoA?tWcq!{b&B z4{HCNa~Ck)Xa8gYcW_%d@BgEp`u5lM_^f$(i%+sZSNL?)w9<=Z68d{Ystk=5G^m68 z0}2lYoyo^upXuH)`PI_;kPZeu+3jo2%=)TSu>W%7js2VKnAbwX!UkkFNIejM!y-93 z*uyixBrGgc+aNME$2GDv-NP>sGb}dUuh9CCJoE6$Raa~Bwx3(PyzqLNOTOgKq$H!* zyX}EyAoE~hLC`Hg#n!Vg-7kk>Fs_R@<8;E^cXCl)D0p4l zfIKn@G25I8)Uf$0VmR$xFdodH!z zZT`RjO>3a|fSC){kHkS@f~7zNIR4-~SXzbJ4=i^&p>m9%{0vh^l$(~UJwRhO!SW&~ zyat=wCJCttfx-)3-VhO&@VrGtnFPsO8yD@-I|_Cm zvU_1+0v4mTy~>B(7#OhI%b+uB-<5f115DR`uKYgv&AvHV-n&0-unL@d`Si(vqNEgG zuuDnIm&BAaOus%f0K*!dm*Fu6WFQ9&R2&vQU@lSSzg`EbV~8~$Ykr}DJ(TzZBUq3G lkeKk0#8rL~mG-G!uYg^JJq^Ob1ndWD+Y7GGu-gj{C;OJe}t;=RN1V=Y4_#xn^k0vwqo>ty7ySMRWkAc?rvh{NDAp>eUHm-et4eahPmOM;M zsJD|f8|tbyxA%QLpy9qbT0JE{@j-z9SzqeApYzvU=-NgtvsO~bO0%{R3W7bkXV#^% zJwiCRXShk`F+)}CS}P1KvicbD^%5?0XA8M%hXZ91yv;wx0u__0i2?5%-}NEAzjtS4 z+-?l0in>{Fnc?X$R!CaM-1?j5T4jNu@0127pL&}fQ}dzw)liO%mL0@}yr9Wj5Sugj z#g6jC;LM)4slA@bCJD8owAR&8^YFqAdi` zx@9rt#Jig(ck=LgS3^>fYsGpCZe8+#5%bjEE8c7aOYGJF&w4;M)+TUYU`Y&0el>DF zv4qj7YfQ*LR5?jVRpzT79%*rn!nrmli=LI}W5oVz#Rc8*>lzK)2J`ntUzy0KO*QGS z%R1XHz(9t4?u+bZ@Y zQC6oRNTdkjQ9At6M3uGq*&5KVWg@l+>o(P%Tw<2h@TFykC z_Nj;%!%a8F+Z!+L$tT7=S19E+XVlJ7{;XwOgoCNddWm3ynGk06{)PrrPk<>U}e zKr59+ceEAHvn`+o#JyKCW4vjOTj3;Xrhb5rAJ{{vBqN`^lCiJ-4Ticmi+KX�!iOm_z7SH7^M2>`bb}NN zjbG^Z#C#dqS6mY^D$^}*Ff3nM3!xZH%5rpysWMWp&wSV~UrF8K{42#-Y_&AquWKbK zpz?jcMDb6BvVw~7)R5iyAB%!6I4-$No)lSwf0Y>)kU+@shw}}IpNBnp08iT@UUR@w zv8cP%(j&v6s>e>BVpt|~YPgJU3*nBO2VrAC_%VI3XIlKgyKoE4@s_5)lFuu*`fuMk z(Nqmxj}c-u|47fO&gByd;c)myS0X>NsFv3 z9@s=H9!_v(+OeIA6itB!WX@d!hLb2Du}{b_Pdwl*H$?TIx!gw=cP3py?>zW`!WcP? zi$pGwvy9{gXM|xz{R7UCOAf5#;5Qc2n;WL+*IyYEj2(;Dw}$OY;sw83^T8n!6Rvs= zp-)p>Vo0(lrnAazvEDsrT3o4?Y^Jxrr>lZN3LmMw45gR{yUehh!FqTdi#c3JAZ^zA z1Zc@tX?3DC3cR1&9`|6{Jli_^?m}g_W1lCfNW?$*ekakjX)&K0rj;XK8Pkk8`i)@w zl6b)!Oyi1cz$K#0pzjZ7^gj+i&QW+TmS4u0k2%Eav+C0|X$=sRn^~fM2SLP*7mEop zH{X7hs?0y-7aBdesL}M4a;=jmfA#PLtxayRbg^ni+mrm>{<4y)hzbNL#Pbw=Q!vap zFlMpWIC0ZK$Iu+!-$g2!W*Y#N@SCp(_F=UtVghpl23#U${gdYs@ej_WE2@db6dBG9 zlZnq)#x&!({6?^SNxa~?Z9X{s_*^2~*_a74jTSuU&V(%LD9sOrbp_lH)Ty@@CaDJ2 zqzS)<>om~*@9khuvp>`g6n7ae<4Vl^*7%2 zUV5&rwiHml3GSSDbQ`Ce0noJXJ_q~WUTs#NV;|zKwdefXldC@GfCs`1_&Lk}0E56T AcmMzZ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410112 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410112 deleted file mode 100644 index 18b155faf91f7619d8f337bc538079e64bcae1ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4884 zcmZQzfPjfR9>*6Qmx(P?d}HL*_Ulhh``Wu#i)S`T8-%EapSbuAs7m# zxVnJ%>a+DAo01ltm=Cd$fe}PsEy}!^6!6_Mmwoo57p6jH@BhEJJV%dh|LToS^5TEe zWq?W?KL6>Nf7ESBO=n8M&m_ZD7rKMYmv{W=`6xeQd;%dU4AZFRk4Dvt4!<>`Q(a-Bfze zn(y}9^Hbhws7L7=_FijhxX*sB`;W$v$2+P{NG!R_xHRrLgJ_Eb?}Kfdm#2VS%zXUp zuGl*u76hCEiKa04csqdTZJw^B)8BqsFlo=$J0^BITN)1j)0wHpdh+v^%TcY2QJ1Fk z%;tZ%wOd|&p~=s6`lk|}Z7FMC`DaV{|8o|)^9yb!nTPjinCSHW{KSy*?{8{QOaqtf z={bol$_}%y72nL@FL!x(J@wftrLKij-!zpNi3FaUta{4$s#bWHlE-8A=*Qb2Zem~{ z6jwlXEI`ZzQoqvEsCed!Dvi{zDKE6EUBnISfS#{Bb6^@f*RB$g zT_$kNsCCU%O$94S2i~81=ByLs+k9-&J&ucq?SSgUJ<49dlrw?d0!$CDVpxwEiAn!I z{i&(TmSxZ99SmPAGOhFUm$z+-OZjA@o%LC1rHssixygSyrY+gl?mzw2N|nCX5)S(O)mS&)634c)JZHpf2aE}$ajM*02c2RaNKer&o#Ues(D3SRj%2U5X)?n9bt^2xP# z{OaU*)_i9*;5q9XnDYPg#j2TJmrn z&rE%jlrOGF*uLC1o&IQ(PEN`8i6$V&gY<#*60{Gh?xpSJ@;3ptn&F&v$&5SfHEoYg zerC0F&G8umPtM<8mT?1U9+P8;r(Y0|0R!o$t|eE@;w$al`YT^=aukQ#sS=CVj;07p9yM>_1>w@}JZBy5m*$Ojl>~m2E-!*S!-my~BT(h)us65p~}1 z@tV-;-!lUmq%JZyzM3Q3bEa_KRLg_2qN4P@Q;iaYU93TA0h}HTUpq3-*r0f38jEW7 zE0u34oZQYzojyu=o_QxvnobZl1gcA65D+`fz@QNVath2LAUbK$$)iv)&Vu3sD`R65 z3sZ;!m^xy^k0~HDD8R=Rq8UVz8ZJ<`I@~G1{{ zy9t&SLE$yn+(t=wf$|GA;t(7rNNo{t^er{EQ+pkJ$4sDUrlzY`Z0BLK_q?n4z1L=| zM=y13JzD`*1kAfw(&#U!94w83%6c#$qMQ@cSmclgOoE`Y)dHxA7pfIZAtg*CCR_!s zGzzvK=)ajzl_+6Oq?>^GmZomPnnnkS+b9VyQ29iSICKET9eNsFWA$|Y$w;Rz?Y&Qr zy~>R{<#$m#{9MG{Kh_&qEN8`ag4)X<0B)%QXcP1lxZ=HCAuTW^ddjgs&Jwc}9$Qp6!K z;Yx6oGY%jXNNE(L7gSGz>K%9)NU%S!?mVEJX4i}uRIb-U7pllJX`oo%f`5(^i4w1Q*5)B z{+SKcPeeXOgfqc@2&_Ma6gLFii4xAlng4taa@-RzA8Y=ifjyM?10(v71dy0;pOTYT z9ALUh^gD+ANCHSqnCZC6Vn|v?$;U`(nHV=|t!#qDJBGbT0!U1f-Gq`SiS92W`2%hv Kkb%u1FnIvu(vTzo diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410113 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410113 deleted file mode 100644 index 13421a93a1f7021c1c097141559b6bdb12200ad1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 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 DLZM~f diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410116 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410116 deleted file mode 100644 index 36387fe2ee8e536942fb848128c15a6ece89731f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4696 zcmZQzfPlH|m)vAqFTXi1_W7`!=E2@yHj+Naryky~$?|Jsr)b$jpeo@nY);cmSFp=g zY?s;@K2dJQ4B1(2Cyat}9VV|WJ#Zj+^<1uG?{ph+SFWjdj7wq~8aHt72yS|E(M9l> zef^n@Z89L6k`|rV0S5kzl|71*@9R>SY=0W0^V54TP@$sgVv>MnC6pn6{u%O#s` zpc02QCu_qm@7v+t>V42IS8Yv}yvw$UhfF5O2Y>rLZThY~p4VlqDpJJSEVg+~EIRf1 z&f6CX^DMQm%AcLZGs$tUpfYoac|l)oRmh$Dam$UR=N4$UJmkpkKexqrOO}J%k~>bT z4m-vkT_&2o$l+m0`10$IBw3ucEK=BD!OX)q_x~v~MIHvx78l+J+cqyx0lAp@_}N`4 z4ImZ-oC1laF!*>ofaqhw{{^UOPW(sY8bAy7#QgMip+1_q4? zAR8QSAblW^wCLm=AO#ZREGRCpGB!3b2WbETm^v_>;ve{wsXUJFShc6pj(b-wNJtX0{ zo%Pw$g_~r;E-)KCGtk!A|J>`{)ZdGK%AM+Snbh86A`aXW97M|Y0p}9U`l~IxI zp^o7Oj<&WyIZ&8`!-JsN3=AN5Fv!mF(FkaGb+_@>L92;dehB5M-?et}ogmy-toQE! z+WvbW^MYNSK}x~q!e|oo5%wq0Q0rNz;C9f!?cneRxg8v?z&yXUb-rUYMBMYv~C(_eSZ$CDvdoA0> z%?CMvW`WK0)qas;D!+lncz)B@Ut3?OC8W*JoVnrU*#|=NS!b~AU&p}j zlc0VE1~!npp>e=4!OSAcP2c1(Yi7+mbF0g9Hu3IqIp&_V%u%+oQ{wCs7KV+B_UIi2 zSpf!&U^f8$>tR>@c3!#c_S-dc{5P(d*yzd{;pm=Hmz84UUwrQRe)q$?2gPDr`yaRD zyESvQ6|GPDEYcKWy02G0UMcuhdQoR5`+ap*3-3q8 z#>d)pw8{=Zt<-_g;Is&0g3}pP43>t_#X(`o3=AhHs5+w34AZX z;4ndI2f*qfQ2GKDWZ?8b?eYuka75l?fq4XMA0!RY!(LV-dy&%!z3qmj1De zO;=`^)oIcs#fNzGGolqwB7K{KAhDJ}=L7aecQ~)r|+LFa=73 z;{?b?HUpMcoM46$Q7oR}#K6Uy9#VmA^8i3tl7oOumBo)|cdkb4l&Xv IG%mpu0B?z+5dZ)H diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410117 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410117 deleted file mode 100644 index db5ec06fd7eaf71ea28faafc725a753250b323bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5836 zcmZQzfPmGLzfC^pb3|hHu5VkkJ(k_w#SwC;Lb1Xn=$TS0!}Z2RKvlwX*)O@twqAa7 zTMv!bKdEU`YkO5Z5cLe#cLfA-eXxgU&y zY8?!}oQrw-exchowI}g)vzujvTdReSvFd-n{wtv6eq$`l-6>)%pH@GN=aV|8@G?mL z+g+>KJj|Wio8juc-({Jq&gFm3t2oh=Oq|LM$BV?Fu#%jKw6#;8lvd1muJ z+}bU#zR=|7I{i}#&$g7cul%#6{Qo%%-T4JKlgz_=G)#1Qe|};}`S&+9D5il+_Vk>@ z7G;Oo*NSgu@Rz$hyq@}Ol~UKjsc)J}j6?!YPF6i-d{ryFOUdIgd-UUN5H~R}5Q;0H zIu;;i0;y*Up5FPZ_ULz$kl3otInUpD?qkvqYsh;vH>fPc@Y=K&>I+wJl|Rz8>u*+41gVofn+j9T2sRfO zw-yC2W$PwhvhOxCS$I;yI44m&ecr;;*KMMTI`2d?%=_TQmhz^v;p5I_&p#T@OV7N# zghx`-QhjyHiTwhve#Nfj2O0?WgW+pO<{29l&rD-c&3>iwErpZYS*g=UDbF+SW(gF4ioxj=|G=kA<#Bw+sy&r< z+`H(>k}GEMmG*A^m9IBBio@+x ziN)*k3;_${by_nQU;7MF#k6jz14K0gBh;-9d}?Q2=kEBL@U9{L^X9DP&ym^RBg`fS z7|+p^sm?9r&_CPd$kB9mji%q$Kw;HrEeCBzx>bW?R6(*x7)G{_YP_J?`id#%D}+AgMnGAje)r|3aA_vHlkDb4o&L6<=IZgiw>ZT2 z&$Ciq(OQ1r$jcq11_-EPr)!7@*f6y}RsYJ=OU<-a|Jh_TrK!s*di~Gqrx#~!aqWAh zuub?9SP_-%jC6_s8#gh{;r*0jC9*7P6ccxA0xJ3Phb1Vuv&C|jPZ#W-^+Q|rs z4+e)=MMkDWF2~oo_U(1I*6e!N)h#S$IH4o0(a+|CyNhv%&BhB=>l9xfzQQ@%QZ&y# znY;V6Q|Q7s$x^8jON>}-LE#0C`w3J~+`ex;}wm>;hIsm5;f@U)? zumjaH_-emMF_quIVm!a;>#waZ)DqHWXwKa5^6Uel`K&Y8_OAn(7wig74zRQbrb*Dp zK!jTutY@79Ifqtm2ZuMvd~mn|%e9zH*SqdBR5sMi@akIW(EaYW_3D7KrA3u9ME5xg zhPyA2Si1D7|Kr%Cc0K0m#H0&hEs}?uD??mE{#Bj2y7AjnP}s37TO05q#>GB!(|(qQ z|I1QEc@2~f>qYGsG&}V4RJ>%RCdflTD|H|=IBq~paJWOoU}1_b4stIuFz&$t50WG% z44Hm?kb$NbWOKPe`jG^Xm>?N2fQ1i?4@yT2F#CaRg7r`dMxYqH^d!zr?>^AjO(3_! z!fUX(jgs&}juT4a5F92*?K)80!otf1$OfkeYUgKgdfB*WkKR!*3)Gf@0a%#O!(LXH zr9c|yXHa<1+isfr8C-TE!kVsr#$z`<{mh0G&kS6mdvQxDs^rus8&j zH|YIpkQ^v|f#pE*B*rDWUC0TJGPjZFCZ0R8u=GVMH-XwA@Ngo!AB&_16uvNkEpQ_F zv!+_Uf2^=*K``5|!p~b)y{vk&W#z2C33Gg9g(D7ag6d8A4+KCq%m_vx_a9UaWCnh+i**O;xPLl217{nu!f~Iu>HXDVhdC;O8O_xO%M0b z*i9g}!@>(5uY<&Gl!O;(+=3c$2o4jZ_8K@UCx&qCn!P4g+Evc-fpx8_so^c*kj%R; zF4&%Aeb~~oU^XPa8Fip(6p|i*{bZyxii-`43sAiU2E>dREKY0x2pyLI`I{4}6-*%| xSR^J~1+KIUwjb#4nNXD|aY3A$+K$rLO<2?JAaNTd;RPC7qDCBIO}ns|2LPbaZOQ-u diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410118 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410118 deleted file mode 100644 index 5d5234d0a0fc97954f0a4669138c027d73fd3803..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4876 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410120 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410120 deleted file mode 100644 index 892ef45d70c653a22339ebbfd1a5b34e3c6003ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6060 zcmd5=3pAA57yrhayd^4K%XC#LR6`i1Chx&`MGr}2JiA0i4=KHbFd~miDbGt86r~51 zi6U-!{!58UqT*KcuQYVe`R1Eho_4+OQ^&bWC!XQr07`*AMe?I zy8=v31{KI%G0yo-J*>uMnOM~R&0BP4lrsZGB8%?IJk)ul(IMfJvCG&r0nW5O^L8D3 zMg#}j)=hp7*4uxe1c)Ag+N&$S_|GrB&FNYq*Upp}t17X4Q~-p$c8i=Tm43eTk>j!Y zWr1hb;u&w$%$e8c2KRUlup*wQObQ6vJ?(%nOR9EtLfpFZw>yv%0|csouE@>AQ!-bk zi*(Zbl**3PtYFogtUJ(A7~2*{+-J5?OvY9xb6=K$gZIq-;?f0#h`PrsqXw9&7nADU z&iC!3RJG*~H-x>pmm7vC?zfccx^O;^1{n+9YPh_y1!`=mgS|Aw#+nS<3ly`E)c&DU ziC4=W=`5LF8gXNE{?S>&wSz;=E(dTfO{tQ{WuBBBQk{KT=MzJ_&b_BJ^k6=#bnBNt z^ffbr9<0|}89PU3e%z;b2yJx4%h5GLV#b|xkNq>r$J;hP@RiwW`s6=eJq7rf)5)** zZdo+hp*Bgqj?g-HWenc(ndq8l7ucK-{w4R+R8bR=p%8V$ zdupyR`?}=UPEV`vx2+BZ5b%vFY7s;&3Fv6tpdAzt&mOkM?Uw@2IA?2iub6sodBoHi z?qv!pvU{XMZOHOV^kLO*JbN$*aE8>t36z@AGH*+cx%R=}mb&??dSG4PKv2OKsY{till)V=^*HZ8yOGPdq>$M_`=L zSjmPrZkVr6u-vP)=a&x!cPBTd#cV{JHaRsf`6VE7MOQkV?>&N zjI&4yV0|{SRjRkM^gDWXX}|s^btg~5rtKD1A9H$=6VyY=$-P$?XWvS?4>4on6X?|T z1zJU$TA=Sx|1EsAOfaojtv*FaeZ$LN|4S2}WP*>j!3RB2|6A#)PL?jS&7U+TwtdHB$>>Qp8Y;}{a38Uc4AGcCy8TQOhTYV>DrSg%% z%6(J-6tH)8w6`&XCT#JkYxCT8Ogbd4YZ%v)TqBO8ET~ z42|G0uH;2q76q#fZ8M!l_kK5eKJ{SuRfABK>S@+?YbnP_Ph|;R9)qHDB7Rr!z7Wu;QP`@NB)^{=2)_ErEw{t*`*qnY&>auB#g@5j{8QY_k z8@h!Mk~jkPI%9wr!sz(E9 zou+ZLxUZp0K0`Q7_ti#^mtA# z+PmWpZlvpqA@<$g16?aGd{sYa05vWSAMFM?YE&j*eVp*=hky0Jbn zxP}(8mk7n0-|fuxy$|dKmN`*ZJHi1m z;b;9Q2ThB>;5ar)T-&pPCmYk;Q3jHBmC0df|TX@pdpxUCuCD3qOUOy@{wj#~8GnNye&N z04Fy%9qcuY%@1Nk$6nxIeZv9qaRx(9Mia~la_9K#XXExG{(|Q<@80@PV~F~Mrb^%M-_X<~T+Ax!~A7U{EwHzuu>4WufeI9U=)AP+* z1OSOmGH0=R1m@@%;hBU-vxK1G1}h)({*C$3<$>W=ES%-TvA8@FlVKiXk5v z+-1!E?`I8eoU?}OXFh6TM6{@D2&;?NfH~m(kSjbqc~tJ}ujK$bKga>jeljLDd~!;d zU{2$%RV7!pc!WSOKPy7AF^7uI~G+HaGEP{veO|KRx zu`>ggfYn1nSf(g|XBMWTbvmZ=<`i!~j1Al`xVI>NYHoqyfj7X$7})aW*4&qO>b ze1i%v9(HhQCUky~$DFk{CNBJO>UW=DPLMnNL4R@gr=Nt|kNAtXUiy(3j+@8$4G$HW zc4o~2BQM^abs#ac+D7QPf5u;EOEl@3l=uby=K*EBy>^)WitBUkUii!;_diDi`s!9R0t0Eq|Qk?oTkMadY%1;Wj2mzmpTZ1OFQ_95+Wfk^c*p C`l8PO diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410121 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410121 deleted file mode 100644 index 48e472d68540518ec8ba5aad06587c753c1c0fae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5948 zcmZQzfPj;~AF-J?E=_OR6rZQG`~Izb7q4TNIrkfcYJJn%%`n3Qs7lyf&AZ!EqWi4q zVwU7h7tR*@G?sq6HRHg`pLaLyocoxuS9{%~+I1f<9Gw6Dkh+6~oGMqrx)<*&oeszB zDE4a2Iy@U>Q_`Xn=OH#SFoNi-MVU8~0=|3Zvd@0>!c@rY{r?x2=jgHRU%k;uUi?qG z3{Z&!%SMYu2}^eRADC~ji*=hBtLm+Ta|GFbFKQChE&O-J|MxdJzr5XZI2~B79h!0d zeg8h0-@0?{GnPIsyI{TMSlBC`8!zs#s2#eaD__}hZZANYDqF2Y;( zUgN&(wAa3`)cjCU!bo8V>%`nW@Hl^7EI=QLT(om!|W~ z=6|@gTV8#k$l#E|muZ)#9X1DEXS zIf*UG4zsTn-^}1IcX@a{_1P+=u7y+IG?f^M1fHC%ddm2!R(O|^$7A;B$J-!oVqhQ? zS3q^FK+FVEZ}{4gdBz6CGt*d9vtOxvOX1{pR_gRo%Ja-SdD3)(upv-M3WI>yX$A(3 zSRfl5ZygH9&PRLfz`{r~KOaY0r)M&V+}WcgKb8J08C7YS5JHlGmqjY)oxG zb8tcFtH(?p`4)T&!)NeRU+!I~HQ|IONBQSMu{Wt^>#~`F=7GcIkL9zYL4kcsB9~kI z=)AjRDm$N@wuaww-!Ew{@?Py14KQAMA&& zX|F@fCr-ZWyh1o3WWsGvVJ@X5$&2O)<~Ut_u%ylBC3zATbV5+!~q~m_qp=C1ABLZ7-L<39!`+=d4R+++nY2du;MEtEFp>&k%TW{{FHI zkpGw*LwqBHKsum+n0S>akZOP`XN0(u!69hV0`}$KPk)d+x*$d~d`fmwq^`@QmENL3 z??S8MW<~wXbg-I}sdqp5^pbWlMoCd+ozt%!=i2hlExHjfZS!P(PM~?W4 zmYuQ9R?Wwoo@zbt-!360_`38_@X6z||F17&0HrC>7I&a}kRQ>*IjXLh{(bmSFN zp{sw6T%E_a&BvcE@Sj|Dbn(2;1wOkYtHe@$#Uv7vMLj&GeeStgdoQ76%ORmH|3x3vraq37jP}dAQ&l0ZG$a*EZ=Hd}awTIv|%B{ExsD3gKqxc2L zhXJ@h1!^y5>sT0jH0d?UeP4B6C3e1?#skjr**xou$&=D;*4b8b#rs=K4~RB!k` zt2+&Kk@*7sZ?4VVyzb5K3I2_;OMvRcJ<49dlrw?d0`#}Zb>`@Wk8eg~1<9swckItK zaD6YmPPS`55foK0Q(<+2DWk<9DJgd@I@y}FokbhaLSXCNk7BB>`M+s@=&u^V_RcI;qN@G3t#s_8B=kz!{ zfjU0rKM(-fu&`qUa{oc)KyknfEd#(pM3kir?CT#)fR?8*Kuw@>7!F{T00oekaA|Oy z!+9XPK>$()f$G*%P&r1Rm?xA?O!*FSlMapD1adnpyat=wCnnPjA4DH*-co%r_3NH%q06Ch3~Gab0IoEHl12&EYp}cv zO;-@35hNB%P{NNm^PkUwrCWr_5Ed5mv8Ejw*h7gwFr1AffW(CR7FS+IPX{2qpnMLB zLwLR+(eD`cBMBfe$#5HqZqi!W1dDeJdyxc?m?XOiR35^^iRkthk{-B?Kn6C4_?xsT z3GBEhT9IolbD#BQe}>_#fJaI%C;jJGYV0rJ3~S7x=Sgro0ca$!UIeCn2!NG`ptc4W z5Nw+u@+MplOfQJW;$D#8m^;ZvbKpH)05Y)F9O}2UWbFDIL+%|-Fh~G&dIT>#f(_C21P|NPiFsm^U|TS`}Q0wTfYaI4$$ij zs4$pc_WfD~~^Ot=zII3NR9IfI@?L3&~BOn4bca6Dk$1Aez( wt3-i%fpr1n1Z0aqY%C5!@jGGj?|=W-e25hDQQCh*k5eGkPso12;(oX^07wCJ%K!iX diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410122 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410122 deleted file mode 100644 index 17c1509e02cc6da1833fb82660549b78794a1b7a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4908 zcmZQzfPk0+*^gDSEAxs?%xeNBaLDX<7_7j}m1NAyYWM!*3f~%_D&dpAAF-J?E=_OR z6rZQG`~Izb7q4TNIrkfcYJJn%%`n5m>&F4kG^S&%%Ibfbj~1>@;z;3a7rC|Q`uDDb zKeJzaUjwo!Y0-%*5E~g7LG;#Gfla$>HTD5v0= zIa6=H=gpJdC!f3LHi!DuGEQH2lgBGJExPf+#(mGCoxiMnFSzdO8J<+d8<7m6Jz;NU zzwKZUxv26!V(ygu^DB4CZr&uNv4+8>vRl5H@y2|vTn5n=FWv{+HZM;BxtRI**j=xv^^rPJSjSuknO);lJ4I$IhJ{?nPM#(MJem&;MDj8T`S^UUUd zxV2keeWA(Eb^50go^2^>U-@TC`Tuhky7LQeCYgu#Xqf2q{`|y{^6zhIP)q}t?CCj) zEy@nFuNB|S;4gQ1cs=#mDy6Q4Q{Oa|7>NX)oUD4v_^MWTmy*Y0_UOmkAZ}t{AQV?X zbu2*41X8cexjAX6?vBz^z2W<;?ljaz<_q+{xi)w6x;MWk_&3TfVc>Ui0EU4lP$@Xh zKze`xna!{|_20fV;o&E;Wbemi_deUetg}#ik?^f6^QB`iFlswTgEYvVO$AXPzz8-M z7`Jy4N;MOz@6I>-8?)@+r^R<)XC1Zv5ZP_r(sL(SvaWhZba|wcxP1TjjR#M*wD|wA zZJOY5%;me?w}-nw&P{8u1i2sVhYefr-!YMzZ#n5>Y?6~S#yhC`94^>l3ny3$l*-CJ~V)6AYcTW z3-rU(Sf7iPCQGB6l!N~jJ~++KAhs>as%p;G!w;h-PgM42bKU)5aevu|Z1?_;ZgRTZ z25++bL>Z3W`SCevSN5(;$9RBdf&F0k+L3w22E{YeSX8rLseDV}sE0CMFPBm^v_>;ve{wsXUJF zShc6pj(b-l9-$6CTn$7&Aj%_!jOBc7Bb90v%ukU z>KkiVw`iAQvGmPC@t6M@y}j~>pr;ocz)|2?fE%*&IU%QBx@U6b+5j5=cAHbtN(qqtMmzov+7Zs z^EuJs{$qX4Pkt%Pf?P@Se>89U0E#P?%ZqaKgx|MeV_;wZKnI%7Vu6}ip=N<8m?c0C z5)-ZhoL=EPkli2vDLX-R-+8DUBdAV+vKfeT)BO`Pb`!|$u<#meZlff;KxHL0;t(7r zNbMJJ^!4(~Rt1O^wf`)S)nwt7IkLd|wLwo8Q~ru?9FNv5a^DY)V{pp>$i|gsP|_&D zx(sL#xGsgJE2tfC3X3Hu;YXbLDRW@y7H%+^(P~r~^XCnz9G2y<&m6y@e z0Z1<>pM&BMo^MF>JBIy80!U0U+(x3Cq%M`nK;s?5UL*k|CdqCBm51M2G5iTQnTC4sd%3m>qOk1+5zxb)fYIq>KjEmq_&n zE;g)ugtv}}X*(=VYdZ>UpF{zj%!$MO*t~)(4T9|lmPNauW})N@;@s3alg4hsS|$t< zw^0&apf)Bo;t;(Y0Y|0Ow=2qDPb^q2Ozx| z^$Cf7$FLts0EtP4+mOm(V%(&)vI!RN81^CwATddH6H0wT^f&~PKj1b38Q2^GlLr7R CB%zl8 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410123 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410123 deleted file mode 100644 index ccf93278b9e89a08a1ba72e5a45fedb23dedcf2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3924 zcmZQzfPf{keII?)oqqBNp3AFAdmh24*JT~lB%pCS)xiIJC&OBxD&d#{*^gDSEAxs? z%xeNBaLDX<7_7j}m1NAyYWM!*3g4Q#hh{Ujy}f;Lb5yM3)j6u_n%)e74nFFfT3Q}) z_qgpdKsF^UI&l+XBLgFd-Wn^gX?LxL-_-+F?n@tTop6#rygAfe=14&Gz9yDSHr+ra z4$k&v-$XwAP2VP;uxL_V(846&i4SK)yq#&W&$v>aX=BVU+Yg4_C#Hq+nXsw(rQKDy zaq{6?gEM`%K4s@`4>=jcacA$biQLo6Cu+L7n#B5UbBdHRVe49EX6HV8eefld`*NBh zB2u@7mxqQQ>$z)jDF4fo(>jG55nrzyJ+^#`Qk?2_2GJI8-Ur(@FHZrvnECkGU8O!C z76hCEiKa04csqdTZJw^B)8BqsFlo=$J0^BITN)1j)0wHpdh+v^%TcY2QJ1Fk%;tZ% zwOd|&p~=s6`lk|}Z7FMC`DaV{|8o|)^9yb!nTPjinCSHW{KSy*?{8{QOaqtf={bol z$_}%y72nL@FL!x(J@wftrLKij-!zpNi3FaUta{4$s#bWHlE-8A=*Qb2Zem~{6jwlX z%s|WpQolO&-@Y~B;U}_W@5g2LKHI>ovrv1H@U1KJrDHEJYCA_W@H;sG!@vuu6dY$D zJwSlWX6O@oy5?j33JLG2Mthe`&8jxrac!Z(&fH6D*ea^pXJ^a?X<+*Gp#ek#0VCL4 zVBGGvnX3Ks|NUH{h3V|4O<1g=c1=iieEwyBy1SN~$E&jkb{|~A>@hWcGxw)UXXW~4 z#&>3aH@T{F@4SKSmVJByQ#gQTf&H*y>-{?>Qu8h6zu8g6cg5z|>a(Xl`(2*izbw(# z=6k{I8&E%Z!qkHt0R$jFfc-&GKLZ0BNNupIGe{qU;R&DB_st^Yy*xQL2i8VUcAt8v z_hi=GqF25Tmab$My~nU|(H^~{V5J~}5$pz_f9=Co)J*MSevnkJ>}znFJ@4`38G`=u zAx@Ld7fs0R{CG(3X{0|7-)yc){{jyEOw7Nazr^82l5ND^VmE8My$w5AfM$XHYxvrc zdBz6CGt*d9vtOxvOX1{pR_gRo%Ja-SdD3)(upv-g3WI>yX$A(3c#!=-3NV;|e#LA^p^~L%_m#oz~37*FJ+(GKujWfa+j` zy47J#f4r=9r1__BC+@y;y;&UmIFx+; zzE?b{5rLhb8FeQFoV>BAbWeo)52*f>|3H9b1S6394=M*s%b@xP42UTE7}(d}KLIWO z;((e!M&}= zA$oZMj>=9G)tZ}zPOV28{A~W!?d>o$eikCAURd#RUEVDIXr80c_(rccKED!OfQR3WGyaQO~(9%s<)94^^8%i1_(M=$Kp#Y?a zLt?^}psNSfTk!H2OPvOj1Di#J+lX(g!kmO?vm(0}r7k7HUSPV0ry+DdA}4fYJ76wA eSC2bPkm?{Z+=OB`5(kM1a}v(HhP5mK=>h=DAf7=0 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410124 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410124 deleted file mode 100644 index 0e792ff9b3253de4b667c3fc0a21d4cc12b8a136..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 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 UWcR|tgeLZa>pAT9f*k@P0OOy)tpET3 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410126 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410126 deleted file mode 100644 index 67f1d1a7a52e73eb1d403bdbde0724bd3873e67d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2752 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 A=Kufz diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410128 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410128 deleted file mode 100644 index 17a0790a93f7fd43198ebf0ec08f392a608d7178..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4960 zcmZQzfB=5;+3G3mZ{ND?jACmEyb`VG$oIyr0b6Jn78$$6K!7eQv_uDzj+9qOYd|rng@2QE`38 zviezv7qgPBS^>9BFjGV0frxv_bN`ZcY)ja1e0jEHsDGWZ|4j_7)r)%l-w_g@a+OzeJiJi`thJ*ifW~#BC{QTu|R4ZfDrRhAg z`5$iWmRDbB@^hX3sf1@+%Gy`{*;4-hoQ3ZEf}2U^;XN8AI=w$XF{J$an;I0;z$JTn zPGXC)!|ZFtH#7LlT^?RfeYQ%eYvI&4O(jMmfhQ-co-)3w72c)f@t8gO@ivH?7#Ik} z6;K@u5Ho?)I~f}hU`oXs+y@KQ}=Swp1J2?Quz#pg- z9A_XsK!D6igmJxnDJK4*Wgv2loKQu(z#;ohgi8&88Y$ev9FQ6Rtw zHWwJT{?3^ON4Vc>FORfNy0EWN;6+Jr>znf5JK4q8uC!NKRA*{*|FQW??HTg2hkQ(L z7q!mU>TnfxX??l#=LG4Oy)Gd4gZ+@=ANZ81JdW>JwWrdKdsjVE<_8?U?`IKWwNGNo z=Y7q-42*3HfYxqhVES$cvLA@yAZgJ_ULc2M@0_=CoA!Gxc{q<}roKta7uO?fU+$Yu zf3!&_r)2v?6OiLU`oMY#+6Ptl()M!sn*dwQaL&49#vS&Ww#Ozvvs$|5_zZz3=kG7e zxB)be$uY#!F9^thf%H??k}GEMmG*A^m9IBBio@+xiN)*k3;_${by_nQUjyeKMnheg zaz?QKfMI#$g~G=lDh#~B63h0Te`vKUWpA17sltfE4<0|e|GRhkffOdgA2#++&SajR zaO&=s_^AhGtuwpf`~S!7Yu59POMmeL4Frefsc)=d-J)HJ#nLwm#b5qs^!B=wvfFLh zg?ooI{P(naO=V!<-oe1E)yBYF8UxgW5|%JW0cmC^8x*!6z!bv$1k508K198lT|I~a z4)f4p7iSQMLw26SmaNuEcJrf7e_K#<_4wXf9OC=uSt+k*Ex&K%qW;1;76qN=X<>yooR358WQ4>Ag9De!!F5*eYFQSBCx1F712u|ocd{kf?D2%~z zf5_+6#n&$mp3~iW!BTd|jn4%FYD>O6eQ+C6iGUi+)rYuUfsQ)bkag51vZ>q7&G1_DN~xuEo`Gj-DLNdY-47B5MAe{E&O zq9*3MHs_w`xlT6WO5gg=p||LP&9gY|;##p=`Rk78-#nl3cKyxzYXFv!edp*=l`D=gEU@WMF;)p|Pf2P&hC{%R8_# zf?)zw1uoklWhB&S1cfDoFoNn7mJBIy80!U1_YlwFniEfg*R4@Y??-=$X2_P{^b`t|~ zI1!z9k^BL-5y-&ikk#*w_J0Xu*kbuvNIJEJY3Fj*olM)C*TMj!*5L(Fz|oafeJnmzS^tiYweS{GMzN!HEv zv(9jicl5qA&F3{lKlhIRKmcUJ+j2neKd9NfIM}dy#|x^CftdE*;P#-5u zFNj8RKN1tJ0#_OY+YhW4u0U0yC;)y@RSm33KAy ev?YwjZo-;I2Z`G#2`|t%05#$eYZ`^dCj$T=AnmIF diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410129 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410129 deleted file mode 100644 index c942106cf9d08958a9610d20ffbeead5ebd91479..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3976 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410131 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410131 deleted file mode 100644 index 2bd09182e856e66328e3217653d245212092863c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5880 zcmd5=3pkY78~!DQLRW(A{8aHR{O8aQhUxf-#0s5_Gx52kN0`LIk)$`=XZYZd*1oZhaf`P zvfj3JQJk_%t+VIoZ?fT8L?xd5U~0oQ_qHPp{@(2sKugvB9FP7mCzCfa(nverU$w)K z%60$Ar}6>EZehQr^Q&9JM@c}1HlH*4k)2-VoCC&Q z!6g~vn`I1mDPw`E0`9G?@tZ!se0zWX(}Tz8R^9DKY#WP1zHFk!5z2ZtPXA#}a z86j+Vu4O%$GXLCPA-C(Zp1JD(KX$WPJA2SY(?nx&@ zmS?H7d!GMRK@ee>^K#+NMnpZqP4P|*rz8*}mTJ5rduuVQ355@P0}-dsX|SxJ+ec@Q z{CW5Qx4N7BnaQbLbuUbE4P=_1{Mqi6NbqXQR>)WGt4{sMu#h}{!j$hja4IJ0$B9$1 zFRxIR6-0LVTX^pMm~66dd<+SEF&X6g)vmc(ErD;z^GO{>o+&zx_vF0q)d(>m$h&+6^rXQuw_8te+P7!yLRAaYceA$xg#=iD4mFRD>Vh8v ziVwudR!vjmJIkWfTSByq?*}C9m0e#{b)tg1kTAv`c4s!}sakHUYaLmf_`C1ov#Bm= zk7|eYt+$!1rlhadZ_^x{Q~;ZLNaa*&U&@l!-}FfDY2ciBb~<~UbRy^x&CQ?g zS6u=00uhx30Q1LwaDDKI#J`Ad3>vU+P9!VRl0+g?J{6AQdT1H=1*4xB>!WmWD_!U3 zo(_6ofy;&7wG?;DT8+#nweiki3en|DR~ILH;biz5%)cJ6B~K}OU$x+y=Fw_sI1pP=~N$87!a>Fsw8wkGrbBc$Y7*>_5lc%6+zb`<^@118&8k7qgug z-8>_=w5hhEESIrC14BXW#Zs?>B+47UFx0G zgZlYTBY&kHaE&oJ_S>PPN=`yY?kX%s*5djQ1Q2}RXd{?u(mHk|KJ;#%*@WtGvMw^T z$idB#nw4_**k=`gM54M{mxEAUI2W}Ge0$!QmZ#t7Xq`D3;K2MYq|HD%?QXAAj!tHn zyLVbcUAKGI?JClkhQ6}0!Ml*<5H=pKUF0-WMAAD%uy zRkL*HP0?R-F(bi}O;o61{r({FXlEHBrRa{R?t^hI2iFIWNI>4AU=7q3sLO(fU}L}5 z4fY#^dS*PbisGJevuyR{FSr)|J+Hg?7$=!|!($-1pZ#LzOQAqrAjbt*nYIeG1!0Qwik*ZcA{bJ(VcN#SM|9$zzs37!KHPZH->u{k0Kg38+* z_W?=kYG`7qtS!%y<(b*IvAn^dX~`8{-=H)?VaW}JV)L7@65l7xjkut>4r{=1DMank z8hr4bIT_>*haPP~c&%6kHw{Z%7cYgm16$v}fRK$Tzj78N!?dJ) zhA~0R@OkAd%o1$V;S2t^;{HJCe=i?mF)Wrl{^3jLU(~Dwd`bKt4o=8L8KrVW?7tkY zAqM}A_``Xc4OrmWnNBRtl;3cU&{&YbUmzcd&ffcCLf1n1fVDSc3Fm1x_zmZ0Ca_%n zam|vc#52gW`jGu`LacUi0#Fj{ZR8|)V_=`4HA%52xU;f&afpG=so z&>k)l!~j&C!nsA}9i_5y^N>eLxrB4z9wgl_;;}0r)@X;1nt8FY&*3+jbn9^sHE=fislD(}3X11+LpbQg$Y(Hv|lT8JCR`tg`Tn-bbz zJO%sz+fguuvD~5LZy5w*KpHASi~aBJT2E z(V943oRb+@7yb6~_H~iN#JId`gNi3!?${k$bBRcvA5-u4T<=r?aXjW1!-jrK6e);( zcoW8XfhB0Zz{YUioUk?`!S@(M?qn~5eUtG8^Wc47Bx1yfRYk-9=2LWiaJTHiG;vPR lrev6U4$Uwoh#lukbO)Fv*rvmmAK2G_;ltO@CFV+D@i!GJ<0b$A diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410132 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410132 deleted file mode 100644 index 09032447acf7064e3eaf2acc5bc230ae3413ddbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6120 zcmd5=3pkYN9{SAr7TuQT1PPMY^`+hUuoX^lPj^layKhHex|NGDX^7~)j_j_j$ghPkU zeq0mR{5m2*Y*Y1c@3UNnVRK4~!W`p_%J*M3e89Y%WbGg6zFb%K9i-D zYU^KXHh);W!OhVBQFlN+ebo2f)9~KFVMa9Nho3;j@t%~R9w5S^02a+PlbZ2?6=a9_7?KyB&{`uPaTpTCEsW_(Fa-#>z9h_ptb-w z2oxJs6{#o72bd|Q28~pBAVuMp%kHb5_uabh=8go{zIZds?>}&&qnKch)4?x~ZYra|kIz2v;SHC%Jinmn$yUWQMpdJtJ&3T=6dHvEg{N? zjHLzGa~m;zutFNw7p9`_E>fLt-loo0OLe=@tRK8Om+gDG;_guV5esjbOgPJkT7y4a zAQ4c%V6Ww7hU#@Q(%%Ne4;-H#6+XaDRjc$;_}AG=x6%ue2V8!&+V9EO8(|ZcN7;Yy zjIxNf+>gH&ZoN^b8z_FJ8vhGQ?IjgXQA&q>i`nlaHIRuf5!NYxJXW0q@O z-KFA$eDwZcH;9KdwY|B`4T`=YU~KL)#E%iInK0-ntOrU0;?rNKr-oC#&$Yltiva{=Lcz1Q=|uQZV6^=QTKcbk7}H0Okgs*%R>N z1UMG+{>gfy@%{4aIQIkS7guk=FvVP+WlWQv37-kJnbeDa-tbMGP7l#@a*}go+j*2Fb7Ez<;RBfLZ`A6JJdjC1M z9-8Ruqovnm_m=eOaP6sMfN(CPz~dXt}3V|w&aIj&d!86`|IqrCg4 z0Kb(Hv5QaW+~3Q-AO^e(^9VPXIF|SIr}9JNgYyup)wr4qh>0}Im?oXk&ji~{>g5Nz z^Z)4Kq%&GRR397ewIn1U|6!W>FY(6{3B#Ty$A9k<=S~c`^Y+rY zJgh%FPvL(~C{6hv753W?XM@?ob&>%cS4YA81AKz}pLB+1Ai!dx`-5*Av_HFHOTg1|9hut%!VD diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410133 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410133 deleted file mode 100644 index 6b6bafbb87c82b8556271791b296f5d547e96c2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5292 zcmZQzfB*rVtTsuTppP9suO~H%h3;fIy?(K#)4E;ljO$J$e%^Njs7kng#c$h|OYcj& z*dq@9dj5FkKBG$$Ch%PA%iXe?_uw1uxYfmaT|xZQ&nfEf`0@ENYc0Qa&(j%o9xVOd zW7*kDI{?pNhcA#&U7ZfI?@zO`}c zKVJsdUhtA0U|M_#$8L!PpMJ;V!&-fZq8^)BvAleej`(WGVe6(c z+58W;cFU_TH2Jws|5U=WEoJR1|7Q9Pl%<`dM-~(#K%qB3!OKyCc4AGt+#JLKEi?&l6`R898PBJ-vM5 zR)$}9fJ($Y%3grg0trU28-VFx|3r?PbCy2wx-l_6q(R5Hx`eC|u z+aHmu2L*E{Z*BY&v9;cE^<)F#NoK!!CJIDFZadvK@kTH=&@8Zj5Ba>h`1-}cbGlnE zSjz6W@wq@iZONCX56-S=ojv7G#+-{#|M~;fGeaE#@~1>-NvNl1MZQ^Pwpp&Zi?(07 zOG-&(psg)X4i+w8Iz3J2!l%W}nU5YC{SjVmqRjAG%01Y_dRo_`Wp-;n7J$^i!(#1k z?YCDWikJkW-@e>1(aNo2|0Z2SD!Q`@Ub^X>ow%6^M8&;bhI=FnEq$T6^>v~SMSuVbEvbkJy0&+!iw|7q~ z32$Nu)2rSBiVtvD7`}F7p0Ppk%rq9&>{lw^QaHJtl{$Tt@;viSo-~~xYzS1B!XO}a znt?$h8Du{Y!$H!bQ>H);NQ|?fxWLNT*u=sJA`4Rorc?X_pE8xl@g1x7RN8Uxs%Ogl zfW!CwEJCdINlf{?uh|!%{31PDdZEQVQQE z6=Rv?9plFwym;+hc7d7=bDq_E|52Eiv9bBTzVG{4?XN!Z0nG!4%c*ayVcnu#ipA15 z3&mglXY}^Eld{`w*@b(DH2n9pdQD|u;NHQ&tkuTATpA111M@G`IdBS=eqd!DQwaAH zuq0vg!OED-?CL=bkokEe`Sh^Q@Ftw3gpD z@^T03WMH6*ovtAsVB^&ORQ)ScFE!Iz{b!TWl%_7L==DFZpI)4`#kKF1!ZzVc)U-3w zDFSTV#59NZQ~vF!+Y@;pHt^q>Hl^bd^%u^uDCjg#3oE?gd>m>gBP2c;92mZ@yV@Eh zVV|^90?lLj9;(P;;Pd(T>D31dKBi`*%=lHJ9rkI;;-uU==DtA--5_={>ih=+ zAR8XPK<+=Ndw6lMLFtMaSdIoj)iDs01{SAPK7^*T7@$5*m|hT#l<1I{a24Qm4Clez z3bj9J(FsT%0vQ9W-(c#9b5q4u8oLSPc35}~Hn&j{UZApq8gU2?6Qs5jIQl+Zs%p9t zlrXhtfz3guJMWhAUkOlkICjsfC)$ds`k??UeWpOuE-cM3BBfVYn1kwiFd(9SU|?T= z&jMOUBmp&n@(~=sECC82G2zl6`;Y-7KSA0Wptd3hR1zi3iF4E4D>QZ!$nCK3f~V0z z;xpA52Rfks2q70e(Q4YLHs2hu3vN1XX7b4V~BYucfKJ(TzZ zBUq3GkeKjL1NjLV!16MBIsoZKmIIqbgx}$9W+M6zFn7TE5y@N$HhzPI(PQw$6n7wyqI3U(5*dtqS$7NfSkrb}MpvKQoE e_*e|J#~PpkkFDH9@h`RQg^qDxvlr?l1_l7IuRIh0 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410134 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410134 deleted file mode 100644 index 7e60093de2e0a15438629d7633887443ae3fa2e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5124 zcmZQzfPfD&(g$4y?guV1n*8D0!_8VpTp!+j-OJzq%a*vx z!n>~aRCDvsKwQ%a2rV=BOz>||zPZ?j;3hz?#c+4LCcpJn`3=D+g z3aE|+h?zj@yQaMkF`qd3uJa1vgpdihJ%zcHmLxBlBbeiK^}&)hpQ8*6>H-YHei;mm zVHH5-;CKV+0|8)s>HsN_7)L>Ift8_&fhm*^q#$Zv+FmYy6JVL%_m# zoz~37*FJ-kNfbymK$SB>+{xf@o_|Z)qON@*8b^MfO?n`D!v4g1y z)^~MwOtMV3wFSz-!VOHH6xGVHIH5H=;^9>%d5?l=oiPtJD_`lI{?gv$5XV2&0Hi+H z)fsHGjf-%(^6ZZIvdv8MJqk^nKRi#InPlXY_4oAhiCYlKY3{zZYozQ&_Q+&CEjq@XgLW#{L#Z`j;& zb*2k6Ec}4#VPOGs3(UVDHiPEfy!q44crMO(u;A0%?&wyFPV+g7R$G~GfrDUbht=5$+UX6P<* zS!1Kpg^ch&K|%X#otFHIXg$7t<)!t-i}x5T;0Kxo_JiSTN9GwD6wgd!QO$m(@-2mv z+gYj8M=8%U@8n6-3Brazbtw!2Vy77xG(h)|^&mzQXpTv~U`q7%n zIV04q4%0F=JYc#b@38Y`bxr58Q_3|Q+w9BE$j|lY4|bKE+WMu}K9TWLPz2uG-B|@`5DDe=Mgmd6xQox!P|$Z_aZ61NxeRl64&uo~$)a6z0kQ zaPwgi)XtRuKmcUJ!h{jX{Rfo;g)K8MAA~~r3`B%81N-{BSD;~?4AjR8(+i?umY_1> zD!_3G=fTn&)P7)D1WL0Yzz8a{Axs8h-BdthH-X#^3$MZEHcG+^lwYV3hu| zm7B1Z7lXuYl!OaSYQI>o@SanT;VqhQA&yB8KFG_luo$xB@J!ul~_d#T+&2m2D(uJkB-0b=6x RFSYH3jtgM37wRMi1^{gD(y#yk diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410135 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410135 deleted file mode 100644 index 3106790205f245d344c4e9f5de54ee5e74b70c53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4876 zcmd5<3sj6*9RFq_)iyO_Ob_oS(=>@TGij8V%5+38ZKPVX8DwoLdU$QyE)|89=xs%z zlF*ASiWC~;ks=9U+o;gPE7acm&G*guhW0d_bdGyY-T%Gc|M9#3*S&)vl0g@6-n+z( zb#P73wF-5j(t~tYT}$m=c$vT0KH=A6b1VQC{nhAE=Y`aV^A1jldG)3t*Pu-Jq;3nP zY;$>8(Mk*+P|==~=;4u-W_}^lXv#`H!(zKpQvMa6S6sj%V871Z(zs&5i?OLw8!n~4 zWLIRAoi@`?`diGc;}wduhZS`c>G;GbyB+gfX);pP%Bh*^aW$+?DU$!tcjegVZE#BwSGwBJ#zJh8wN9G&2(pGM%!fSMa>NkppJVyJt9DLpNUS> zij$;MrQ;sd265P2gt5hy@~9y9hzKH9xKye5cq^nNLkxFCh}~QPoC|D)fpM*!DZ9_) z-{;LR%nLo=ZJ3}pw4$T4$~}zaek)EjNxdOIY8?9j?|rtB*t0P&C?exyUT{w(f6{)x zS}#-A?fN{!9q-!_QTL~1&Oe5#jJcBh(-vJpQq9_0Z}s3=4R@9`W-=oW>}~lYV9JPj z6)`L^x7xrpk~#ayFpnn%5=;ovSF8Zv5b#Ha{G9sL`(v-#rg}e0X>X142;*-vO+I+k z%rsw#=9c?tYa60&B>+BH09etOK^ZV0jjsEYM-WBG`-9LL$|1)-Ol+-QxQ0ygXnl4f z+RSEMNzNo=-B{y0^hEzX@gaeLMRRsg6Uqzzkx&dE5BB+xdBQTAi|jS^L2v8*g?xQ= zZEH$-5GUbend93Cqa3n!P>h~#?S>vw@tt@|c4tIFjfVF-x0Tg5XQZnv8U}Qs=Z%bQ zb}@~Pskct2d%EnZv!$yr)0Q4gru|}7{U|Nmt{g$wRD|x}jgS_shxTzGa0dBnjO{7; zt@SfA=6!F1t>I^s_nAdiaEp@#$5lCGDe3e~j>W~8Mzcd%m*S~UuRlEOeHZYNEnV#0 zoS_6ZR)}ksu1i!4+>zhqJ2}Q($wnN&Zw~gR^10at38^(5kWI^PWGKc?lHf!HQDjEO z(97&2%Wr06trR#r=x8OH{F-9vV9ECH>R8L8(zE? z>@_kTy49$qQYbs9iCZ)P&KX~ zi2gD_f94bMOl(gX`h?5nnL+_9FgKAsRey0l$9r!M0#aeqh ziZ|N>MzYgt9-Sw+HeH?3OEQb%lN0Vps<<6@>UC2)MNA3DzKzk zBg{y#hkJ-~y+~)u)DfGZ+?Z?7t>_@3dO^N7@bsH@+K=C%ERGEczrD9@Dv4A@sWh;1 znKqR=QkPRAM&b1bS{|@cU##p zw4`n>!d;Ue&~TiW^(jv^x7o+MA%2I4Q+ z2fs!PQJ)ar0BHCOBYS9bcH7wAJp937S@g@Uo#AIQ&ADkRB^1U);|y)I_W?%q_60MZ zGw@Eq2kvutN1;QGJ4sS=SYF|B_>3FD*I<_MpM3g7$;7%L=#n0Su-9wu41%43oZ}0( z5H<*;^i=Rn#3AXCSltrx0Ll`-p}OQadw<>(I1c=6LBtFDo3vi#unTfW8e5_s)COUL zK;q^l_lk5Sdv4kH@xU<2*d{Cpq!fj`aYE{*Ql?`!7)8Fbal(8a!--dX@u| z#!Iz4Jii7D6GH5Ja=%jv=a5DS5WNL1arC`gNGYW8b~%2lAj6K=`(eLVU@sbq=|U$0P68?A_`JX1xrW;RzxSt{ fm{bQDQ?LEv8^I>iFZziI{y6#?G3@pIiAVlF?%q{} diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410136 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410136 deleted file mode 100644 index f54a0d0366ae01af53c9b5d3c70d9eaa96c0cee9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5036 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410138 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410138 deleted file mode 100644 index d49827bbcf3615c94f6014bf600e412972c7f0c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3876 zcmZQzfPk+$6JJM``7Db(8(sZV@>=P+4iUCF^GpISFJACua_Eh-KvlvI!Cqz1%B21XFQLglQ)p1GxLzM8Y5qt`64KDClq|1X~yG1a*xE@7Q4?+wnUCbPv>{p8#) ze!{)Kt6z)#nrqOX{NO)HZ_YA4oF~_}+h5wX!$?OdduDvK>IJKbed~L;V(z&mv_6dZ z=>6c!ngWSWVXyvAoPB>;qKuD=Y4(bm5KV^p4SFYyI1Cs>TcUU$Y}>p%1>|Dp-Hm;1ozSg~7+$0Yq=}bS<6!_RE4vd$!&&vD4YoaPXhbOf}Y%pTAs=YGsVNG@WNQ z|HG}_^6Cpsey-C$mGEp!S^LUATgv~Rv(TMia5Kp~yhp=Cr}yV4hLnGQQ-fj}xMWYy zNo-Men0>AIW(I$`%fsub&sHgQEu8wMsl-Sm@Z@CGQ^r@d!n>3_99^#+7|;B8LVGbsKp+FZlLG^{Vm(ml zBp?RI8<0i^AaSsqK<&kB9SdWRCcQ?v@2k#>T%6IB&k#}+a@kHUw=L|!9GFHMSqIUl zjQmkbN%_U@D(X&>dlJ7U9KNwq?#RybRlgYYfa=6O%3i>fGlAU#ObPHh$XadJpPS)U8a~!#yyD)v2R;kl-J1gH|{Xx0-6U7 zm+gHkw9{2(C%hD&%;abHpZCjovjD#(KFd#KN*hkU8q5w(SE4PEK=sIBg3M+(>}7b} z-a_E^J?07jxN776&Q++5nEtA^c|E`2EbXfQQ$TK)J(~)mK!6c!E-;PQHgfVV++xu^ zWoOaHLvkE9&({_FJioDRX^x6g?e?Ixacf&oo3U9XGkd!%H+Z>k{i`#=AFqeM^nEE? z`K)yF`AM8WvzT|DoA~LwO;3o2;zAAs9<4?9-5l41*47=HWZj;elmF)g*hWy?LI8@p zp<1z5Q^W4Fu!?a~gWW$VL1akjD zb_0dkO-a22@H0N8$D8c>3&M2Q>X+;sZ^ zjok!tJ1o55Wy~OP8ztcds=KKXhu|G#1 zX2+Hr-}Zz}w=;moHxYFWqAVa-|H9f=NaY9A9x#O^VWNZ|appgtgIqolFdu8$p@BV= z_yZ$YkOYvJaG!$wgbYAsHoVM3N(Uglu<{(9Z%FhzhW$taNKCK`Km_q_Ln?2Hag)}{ iCRn^<*o!29#3b2G@Gu1FB)Xl5D&*- zKqU^@yBwUnnbcVhih9kQ_VW6gl}o?x5!UZ}e7xa{vG0=67!v z^)Hf_*jKypm)^;a%@T@t?(}kf=dFp&({5}K?T_Tho#1r)(abBs^|8CBF~8J&s?4Kv z{;;~sDkJ6}*}LXz9jJOSKcoF=$>-uz^X=;;zB`~dOdA{lw zgB~${$P=EvrYd>YBwa1@B@IELjM6M}sb7w&FK)Y|Ecxup0}qhHWzVL9C=g%-n+x=V zZ+sm0N8|jwo#nrB95QBQOmO4h`0t{6V@0Y!@3NoQHaXV{oV(R{tj$;7&Uni8*hZ&s zO9Q$#hPj`RIQf!S+K?G&7C0VGePa#l7VT0jmcCgi{_;Pgx7VGN-EPY++&iSIFS7yM_>UU^FV+XLNPFfa6bVv37ZdA#$;w!4`P7KXABK?aRzZX zWal|-$!eWsH$Uq1w*@s1Jp!TQgUzvKT znbzt*n~bJ3by-EP|9SoN;;b#MeXkU@315O(NgX>Qog%=-O-yrmKjq(!x;>ExVgvu3 zX;V5bQGekai-Jz`w6MY(&c~s4GD6~m!6C#n?rnDd^Pa%JukO1`1@M>87u{*drF}JD zTq`7AcGB9=;5f@;*3bTzUr3$Vv_St?Pr~GuknSU|#Mbmpt7f)j2bu?td&Ad`%riD9 zo|(p?n*B=UTM8$)vr?yzQl4kt$&;oNgbjh}QWylpPBSoQWCGbJai6s4R47!8v!J-Z z%GlV%z!WF|6@$|${((=K%H#NsReLJ!xOdevWq!cn`+gQ7R{JETeBRgW3slGy5E>NV z;|kIO0qLi%C0ESiEA8F-D_?JN6o=cX5{uX683Go@>$GMrzV;cUiuLP5sA>jAs9PP% zu6fTm8o288gN0U!v(BBopT(w@7xF+T$lBhHDv{h5VMV?6=|g0&eF3wUU%43AUYq27=p+Ncot6J5kay zaptGM;s)7hFdIuaV9k>>u!j_96)&F-dk4N}eRTkB8(BxQ##tHivM&W?lZ{vQ>FUYV6V&X2lq3p|*V&Hu5E{ zZ_C~MZE|%wRDTMzjR!M=5vg4VihGoLl8Cl61N-{h51{So44{5is6Ai`W(kmk#DuHB tmDa%ZG_W0@0ab~T{)u!`4UOG|HSZ4+w^0&apgs{b;t;(KhetYy0RZDfY+?Wa diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410140 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410140 deleted file mode 100644 index d08b2214abec7e3739690691077187461c63141e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3924 zcmZQzfB=#Ftv{ud=KQK*erR^g^YFK+d)FF@`+FK*h|b?>KIudiP?d1{QP-nZOH=f& zXO&#D(bXuNy?kXOQ{JXUl2!G)yXIasTXN4N@*;fLzRc{2be> z2oMVbPJu*I7<{}PK=d|G*V5^4zbu%vXX_mkJDn{J2mk5JRAW8)`OD>~R>r7H(|Km| zKit|aufEXa=Q{mU3D35awXgiMrTqUn3*GqzH_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgLwCW&)`{>}7b}-a_E^J?07jxN776&Q++5nEtA^c|E`2EbXfQQyBQ29DrdE1yc{w z0|cP>1IHmj{R|9jAhp4+&LDjZ@5R)A{{QL_7kfMUcWh3RdVALK4k1}dN8RSXqU@?7 zR~R-f+M{?d`Ux4 zD5ErsTWka%C`&%O^1uV?-)NBCAO}DJGMnLV+3vTCol{Sw?)vAoV4;j1*Y0Xr zLkFeL1^>>x-oY;M52T0b*M|m}Ua+}9KeY7pls*mRnx)M@W!IW=v4`J9rKPOvBfX%riD9 zo|(p?n*B=UTM8$)vr?yzQl4kt$&;oNgbjg8QWylpPBSoQWC7VIZckct3g$P?g5m-z zV`CEoXr_dz1Jfz~flryrweBdf+;MPFoMbxm>S~DPnko4`5-^Q z{6R~5DDekIupkK_F=3$uN%L?Xr0fEPIoN+_bqc6l1H~b^e#fvMNdSoncMUi{!g=`I zMxvXfE|thY;~m3ZBmpEQ+!e&S2_A+ZokW*uNdAD^2xMS$h^$7%%{@&?tQVhlibvdb z`A{8u{^W`&p_#`l<`!{Pbb!hb5J>qC1V9>Q1S60OE<=H0u(S-%lSGt#4D9P~*Fej^ zOrRN{auW_UG84bN69M@n)!AH2mf`*XGb#g1z+0!8Bn}c2<|LeX4Qp8f(ggr2{*EgE diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410141 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410141 deleted file mode 100644 index 71202b875420d43e9d4f28581fbc3af340557301..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 zcmZQzfPkr2?K*f)@WeV8cfMbAu6p?k{!>AbHJ9D)-T2UGvRl&-s7hEQf9p>vr8&Q9 zm>-%Q^E~`*>fW`6;{Kk77ozibnol}W^<(~tUb~rFuALK&m(N+JsTbVN)4xt3SoPWG z7q`Texe`D&B`rE>0iuC`5ky=q%DkBr@ZB?)efFalrb1@#|G&6AM~`j)>WxnF;(yX* zfJz+xs<>aV*^>S04lDmVp+_MTawX$D9^EQ5X1zJrtZ;g^UZtdSSU6pgb z?%!**4T~DQwWe6s6x}>y)}6*<|Nr@&8|(gOmCtNrtvbLU+7iqAVB6;9DIga!A3w+T zx&_37fKwpR6b2t}2N1o@)3tQ^+b;_y?b&+A#7<{R!@++#Gu2p6e*SVfs+BS7(sZ8L z{13Nw%d0Om`MFO2RKl|@W$i2fY$^YL&O!ObM|@E#2lo!+0H7*hWIO$~}^;F3K( zC$UA@VfMA+n;HD&E)TD#K3k>KwQ%a2rV=BOz>||zPZ?j;3hz?#c+4LCcpJn`3=D+g z3aE}5h?zj@^Mt3bsY>28Nmt8!NkdR5qcn?L>X)PHi`(ufOFp~uz=MI`$pIJ!(J=KO zJwO18KX4op)X%`c22vaB>I~Ay@V9LD+r`eQCsKF)^IEV_#*S-uwXC6o(&vJIXI}4M zm-xr9anT;VqhO^Vf)VTnU^?ItUr=$7C3f?UYucg1^j{Y5+ z)1=;>b-Y7JR?<l^2|APGoasv=c6z2O?WJH;{6&M&5m`CP?hx%KFhNauu zLgj%JBs>m#8D6)y5V(DhdBQ)g+PJ@S6>1}Bk@Ocw&Mfx^nFS6D!`F_?Gd3umnZ}};{YvFq3MaR-Qm2nn zo@d_4lcp1dLHRy~K|t&@1A|63$bOJU7)V-lDgnp_iE$Pb7g!k^8=IIwBw^~nbc%oA zQ>OAbzGKy%N;~dd^-P%`aQMETMTpfti7B7=HTwd!Fa?AL1^Bo^G=s?WQ`eF!X7QEw zZvB<7H#v&K?No`y>+%c%3*&WKGZ$a`3{u1FZhZhm0|6t{tqyPJHGQ~Y5wYb}Ygdo& zryf_UiQUd;Uv8CTm{!Q48XqdL#i@14-IIM=i#5GZDxOJtwd9M`)P+?&C-WJO3jN&i zgB55N^V-W+=eVz3yxe%>YgJU>%{R7_XL4|AFJkvub~A0$bE~&t8-d~S9|%BpL-~wA z?ms9S6t>L3JQD-uGY}EZ4D9P~OF+Xq3#bp|7C3-e0u(@E!ll7+3FkrbHUrFlV3}(S zm16{zWiWNbx#`vx8oLSPc35}~Hn&j{UZDI!jW`5{2~xcYj=tNccqUKgwB|6{Bt3oV zyy7!+TUlge*g6uvf0#NY=!mNlG>*YF7LW}~GcXz?4GVKnxef-zltoOxJ~Tk<0+=>9 zjchnn5GDMGG+%}U^RcEK8rVaLKQMv?NdSon4@QumkO8Qk2IXb+bO6!|i$hR312&7= zbq~mDr1}`yy|6H$iM`-D577=lwwEF2OzgEJE1y;t%_Bz{=j`NIp%3Soc4{C$J0CKp2#fWIbFi2f0fu&6p_kavQ5mPjC$YlX9Ma diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410142 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410142 deleted file mode 100644 index 2add5746e716a3faf975ab28af9704f06d4b27b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6092 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410143 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410143 deleted file mode 100644 index 1291873dc681e1f5764efea22b5c8ccc9025917e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5960 zcmd5=3pABk6#kJs$|Jenj|fT9gr*x^E^Z;x&5)9s(v`eLU6qu#LCw&WM|v462CY1A zuPH-CbB)9;lA4f;avL?8Q7Yz~-~ZqB6U()l)@rYH@7d>^z0dy6-us+?|389^5QR5q z*r%|(bn~)xHKf*V*4mzwZ2B|0^VK%h`lXbUZ9r^$RDzxMeS6`1sy^=veZFyF~OepwJ5jNaF zUU(|_zUNZ6L;9wMhu{5;For&QIeSD(s{e6(YwTQVc1!5}9Wr6G&U;?Z3bm7Rj`E^+ z8OyKbuypH8nho5NwC%dYHg=sK!Gs`_#R|xYf}b#yUl-KY__3?#UC*kTLoYvE_s!jH z(#1+tUgX`;Ow~9fc@vSbrXn-6B7rCi{Lr|8b}YehbWS#+$>i#CPleL^FK#nztc`HK6A*-?msgxih-(lG36fo8aI>f9;qFfT8|ltXcb1IBc_Y zZMePm#YfHdj8pXM?M`GDvr473{>qruh*11#;2Jg}JYWrUM)?n%hs|JY+CwKB1=A|0 zM^BoXl#TYO`m2TNP-0*E*m5uLU$t^hCKb~|btkol*?3O56UL)c=DSH8*d}z*az3S& z^~~(d*_)ZNPj0v8?PvvS3R}6@)0_c=lXqRqwmrwBcOPaC1{ty3#aGttBKL;vkR_X( zGswzq=?8L3A^YKVfRYfpKM)i1$mP5soy#913i950ac%qx*5BHx?{m(tW?eR?+Rw#) z$<+uo-o|pZ^*fw`W68!>HGNp;Igd41=4Sg=wsB5LgVj)9F7CAw$t=;TPoJji_d@4i zhQtgT?LI)rXGzNJ#XydM$SVASAo>A-ALGk9crM|XL~v-ZnF*j}paTe(6V!jg zbXRA(YX9N3u+tpbSo$dq$IG3T z>c8B5#%uU!7nXX1Vr{qa-(+!V_mG5p6&B`-77I)$*Cj|Zz}^S6%2#Zeqq;R=vV1!_B#x z1)fLRX3mfwVy^PgVYosC^;=%Bfh2^k3u60#vf&bsGLYsuEb4#lgMK;@~yPy z;16Zi+z!QmUW9wL@1&&~NoZD)@)EXGGBd;PBrXojmAO@3sdSrvPJ;DQ<2HRaoOfDT z%x3zV-MZ$DS{_L;9desgGwWYE)i8lgaF?#*Ac)pcXdi;W2|FjSi;qh|-qm45LR`1! zVx+SA7WQm4*(hnIBUR3VJeOkJzWPw>;j0gqE(B7Qv=<~>C@laEA^Hkb6sfnD+rFHX z8t{SbjueGh&u>yI+`4UVm2Z+uPr`ERAKs2wM=`-TO$E=CZD2m4zCSqRKaci4er~CY zuK4hkx2i`?-8IWXF8-a9t6o=09z1Z{!7r0pwTE)$p@bW+`Qf&M*KD?~Nq*7H^zQVL z+6(c*f<-l6v`k?!mst`>=g6h5^BSVSORc9mIIJ zUlH(ZggJ+j0QZuD{)xOYupGP#t$-55!YAAa7$C6xY4jZMd(bu{%s$8u3v5mZKCdwz z5fGEp7sdp!+= z=L^{RoPB%(n=n9N`MZUCA`*U<$L0alg>x{5{BtwKy?=9^v6Coq`-4y2%Cfch4FO3`hq-<743ZXgL)OM4bo73Tp6?koCKCHFi|{F`{2$I z$0SGPzW_A?#I)-RV}jUmfAQn`m0wr4 zvU7DIbKSGm*lfuV(+ulnc{PUqOBptcG49nYdkzvBQwbJJHT*teV`xE|gT z5|hBe|A2M&5iQ8fS3%wFs5;H^ee&kIsSs*<3(H H@IC$qz?p%+ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410144 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410144 deleted file mode 100644 index 75866b93dbf7b8d36c0046c8da4896bcd5f43ddf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6080 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%0AVftD24Jr3I(A^bf~knNOD2 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 C9_Y&e diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410148 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410148 deleted file mode 100644 index 4e22f6aa659456e7cdb4413c7231fb7b6eaa3749..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2920 zcmZQzfPhsOjz|UHQhj%jRs2eby;~piQ}xBK*mnMJT6M~v-}mzapeo@MX5-YiTUN$e ze^{Kvr6#Rt?{-T##wO%MURj9aF;lro$-DENm3w1tmTE75_54tK>ecX9*`LFY`P^Ty zL3_=SnM*)6B`rD`3!;I55k#y|IV-VeZYi6u=B()GHA}1yuhKWlv=FuJ(VxBbbnXXZ zpc02v##tMdeC0l5|74cF=$aV53r!!QH@y6D760rIx7qCxzv)Gnp<=yB@Zrc{ z4>MhWbFm7p057p5OYKZMUSGaMoc4(Uuh62irC;PXW1@`S>|s z>lP3T0#1QMQy6@_9YFLpPuJ4vZ@(;J!O1VE4)j|<1u^m<82T(0Ubgh zu7K*8pqL@&P|Ho{+jh+POe>hUCv(j0D`ZhScP3GTw|?WV-``Sv8Tg$XfMJjfR1c0b zAPoY@Y=+9KGkEw8u9wC7_Oq-y zec}9ib;l~f%91jfqLB2*oItZc{$Qw8ZNGkMiSgMy@vws_fh@mQ8GEkak>XpBJyE|` zQvJkxuphV;R{@ny24WPqgY-iINE|FDPOLI7iVGRvKm|O430IC!BD0=}@&IEP~ z(BBElw;pdPmp#>d)r{Zqh{3;}-iu!nBkq0^UGtz*$;kV6Y~8ZkcKj(hx_y~xi9&**%!M+6g4*+YsCGCIMu=ibQn{%siET62L=8MgY1fK zg!#)K4@{Stsxz}_#{bIT$OwUxV8?^f00dwQJ5U@jL(>RY6~QzG3l~Vbf*OsWuvo$f z%7-u&M46wy^Z>G(V0u9`7V}~G0pt%_+CzyyFr1AffW(CR6r4BUJWw2g0MvhIWid#O z62D{Ek0gM^1iJu45brh;<3nqf11#P#>_rklVv_78co>3o5?%Ho`2%hvkb%u1+h&PQ z__aBsE4JZYjO-SN`w~;Em{jy;9SX6CyP*B44U#^I%9FWgV0IBKBY_I7F4j(FfRvMy zVESM*k~@)@Fj-vj39&zEQP3i&N|f|Zl$#D&2h-S1So8iMaT_J!1*+>%08+#uG2u#x z&y$d{1f|R;SZA)guT~T~OB86^24Je60Jjy&z~UejzY}3TzvjJ7q?nJAkBP3!Nyx`A GKLP+K7trYd diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410149 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410149 deleted file mode 100644 index 7e28da78388291b99ebb85d7d4284abef1d5f67e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2744 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410154 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410154 deleted file mode 100644 index b873382d7429f70568184602c6002a95d50fcc08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5896 zcmZQzfB-jDdycgNos}C3es8&Z@K5FUt^I!_c+Pf7KI)6(zUXres7m%6{qr8{6&%K$i@mf)@q;2kk-A|th%2{gO z^W{0naVX7l%ba%U{ExDEddGO1L}gC||E=*=PFZ^-bRmOiOBU~gZJU>;fLzRc{9N|Q z6Cf4@oC1laF!*>ofau%>7g`#=Nu01PtjK#mH)x%qgJS(+t4ijFKkc?}QMe#9oo6=x z!>!%&>I+SNuG2r2@N7$2`^rCC%Kx9U(4Aj!Gs!%>N5e#?_va^ulz)FygJK%EWKYjY zY*BWYeXaOr27kHB!|SQfRw;EYocgAz#7HFY3EK&9X~ z1L*+*WH!Uz8p$2C_Nv^eyT4DdtYJGiCFPi7gNFV2#{pi;9(?If1!<5y3#Pz&!R7+v zcJGX)WeX1VR4zJvw)E7jTSd|${}^Lg9`C!xUv{~;Z1tn&{S5B97B;Rs!=2KX-|2sB zw!OnQa5aNn%sl4$yZSFUfQEtnaL}Z($LaVx-p!$gR}an#uJ7J&TzF%`$`f0Z6!Wic zwphn7V_E}}A5h#5Op`M~jsgOhILKTEFBbW20mA%$mwhP8KXcXe-0x2TQNkZ4u1r{^ zb82SIL`9GqAYcTW5A@4wsZHUnegAfNh^PFxE213TB%ps~`ek{pMXE(Ra-R#Wad~;^ zZoPlmr{G<_U;;bqyOmi}4rEWT$=BSGUd;zI3+$Hyjft(X!T*;nkYsme`%Wdu> zlClX~g=GX9`O178gzPMoZH?~x_T1>*d&gWCsA`|fD^YilY9idh7~l$4%5cV0D9uK6 zV(y=`B-;TEBZmv!u>~4VCHB8o z>t%kLl@rE(H^Tq$iV1q=C7ZjXw==DoaOdXR-H#UiQvB$=QNBQqYx7FyDbv*t=LOZO z7sz~n%?@-YI6e$tJ2KDMpm=5)i)!{Om2WAW+|Ej!K1z9>c_&YrP7pQ(s!L%I5IfDl zpiuQ$Fu&_64eE3J47f@Nos}1rzC~t|eE@;w$al`YT^=aukQ#sS=CVQ;v{YZtsvw14uUKDKG^L6f!#vyJn6+%COZIGOvAm9L{` z*tThzT}f|Si;B_?$zNp)IQZXCcjL#EscSFoxwmE8?x&#i1P+&rn%(mX4=Kzr6Fq2E ztHqJDLQL{Vw3oxZtGSlWdgZ@Y5mRpLjIw?c6nH3s$J_AKsn=r5mwy!M*5i1)yR*V= z7ysfD9biBF`p^LN1S8m7U|zeZ($QDq?|N-hcjuGx{ny`W|Jil#7xxv31Nnz9aZ57) z{4;-MTGuY6U)jRVs}vXu53|h?mDAaOF^OsUo0)eCUULG?W8K)fPwIbP!LNO5*<@Lt z?aSiKJaAw|QL(p_>lKOr9(R+WcBcFX0w5a}U%Wu>Kd2li9GHRSN<5TLOr8<<$gC-W z=HIDc{V>fy8fFP96RrRp?r?V-gVc|8{+(t=w zfy!V=Jir4V7V^l^2^Yf^hu|M89L$k0gM^B-w3nKM>&_ zkoyy0HW2Cu@GRSt=pQHuZ2vKA0AdU`VhDiLAcYSR=2uKV{xh8f^BLAX+Hdg6RH(Qs z{?Pw#tR0X1B^c`t3SQb^Ts~n#RdO$^500KEVO|E&pzs2P13X_5>?cx~7l|{U^1Mg` zdr;z&MDsC{2a*616CO42bPN@NwE@w~W{_Tx979a6L*Qi=(c>9Ndf+w!8Q2^$_4B6a8Lv%V=NHR7@mpPerGa&M!mNaF8Sl8VuSPe2 znnU%IlqU)H!GMN>$6b)}F#&g?q-EmFPl3e^ve95RmT&;2Us%}!4{sXSLy12yoQ))a z#Dsg7qC82W-!be*5jw;bkpz&KB)bVEPZB*=faDLjjX(xA Hhrr|kXAow~ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410155 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410155 deleted file mode 100644 index 52c73b5891ea1ec43514c52576ba76bef67d52c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5132 zcmZQzfB=hozhqZL?MbZp=n`b?|8`DdTVjEk`)?ejD5-ONh@suFfnwdYtX&{?^m z;P;lh2me%l-`f92g6C|POZUf^pWnMg z$8@9J@`E6ok`|q8hSofau%>7g`#=Nu01PtjK#mH)x%qgJS(+t4ijFKkc?}QMe#9oo6=x z!>!%&>I+SNuG2r2@N7$2`^rCC%Kx9U(4Aj!Gs!%>N5e#?_va^ulz)FygJK%EWKYjY zY*BWYeXaOr27kHB!|SQfRw;EYocgAz#7HFYv6o@-C5zbi+}Nn z4u*}3_UIi2D+LjZU^f8MK~A57oTAf|e^P69$GZ!BcWfy{zh6YJ=P&&#D&>jgSNlhwTaUL%xhNe^!62=o_fh(ivJG2PJ?Y6 zyf1k&{pNgf)B0r95&tV|j$h8ni5o69hn>8?PCn4pDrnDZAa4UAT8h!+%e!*Hi`u?i~!wT5Sx>rHMf0C~gPohXRm!AOH#* z5MT=7egb9?HXowi%&s290GZDi8tej&U=G=N4qLKXC)v%9I{j@y&DG<3Z*hq4pJ%1K zqP6_Kk(WDICzb4U4ew?_vd-2abEg*N)6HHYlE%#-f`2O66M$C%3awr;k#eXWq$^rW1q>f$CBi z1jJ4=FlZD5*(hf)eMYKw>rGYIzP4Q-p0vuAC_A$R=&8@J%7g$4Q^3c4aUCa z1#=4n4ck7S+M2OAXT%)s(54XTca zyvM+>I4x@_H2)<4^>M=Vf@q`&L1MyHfa4g>gSi!IKd}DHfXXp~>Lr*uV)EvlCXdorXz(=IH{Fe0T_SeS$AEHEIVj9_42fBgrvoG1cn0+lat0J8)rfW(AL z<4U7o`+@$eg{njeb0Xa|g~o2ennnkS+b9VyP+3onIK-MpJI*pZdfjsBtC4n+jJ>hD z?Pqyb)yTG695pji+IP=7_!pn9N{f=Qjk^mBu47ZW! zCaFs$GSGO(uop=HiAl1XKZ#I5!pV0ERa$-Gnvo4-&Vblouqr2|fQKM=B|Ch^xGSEGIyWzTZ0KDJ+~(Mp*W z?zBq&`b&^aNsCT)Kx|}S1kqQEGH)gYeD};{pZ(~CsgT+G|1U1j(PP`cdZUxP_@8tc zpc02eg}3AVHJ(Ym@N78wCHY-qv!!g^I!_yC^?RqAB^h7&)_!_)sHa4*x_ib=J>?36 z1$P!ie#}#9$bI5vzCJ+hIe+WJwV$trY^r`~^N#oL#0FE*ulsl0-@9>g)YdMs3xPjp zmeiPj@cM4bZ5p}dzw7ne1>#z^{3_aYo(Tfted4#wl^H}^a(EwX+q^sl>YJt#Bay(9lT}X{U)2ilQu27r9{qS5#7ztggyIUQ zjv0uVKd*efANV927V_8U>IZpm4f38 zN=ulhrdZ||W}EnCySrGXghpD1>nGytXaJI6GsA6fV91^k&`pSka(Iq8A$I)Pt-LVnIigZiU$EdR6r{;_Y$Uk;#I z;IJ@!?Z`Z1gW{QKEUMYBRKBHfayu(^`Y7dj=AArgIziYFs4j&;KUzw-4aM{&5FDzSK7o*`giyiRN8;%lEl zYM7FuKokftLfz`Ho=3WIt4P-bnN{CJdV;c!NzMws@Lh&`*^-kn)6NI2pW0@&N2^HO zlUIMnL{9N(mM=H7hLoQal;~exKWSgj@{2q`v%ul9w?=YDt-UID>hAATENj>fPDwfD z*q~v5{&9fUvIk%KQ<2gLSUuPkkgx#znV^0K1~!npVd)_H^3K_R&)x2yCS4-q%fYC* zIKlJu6)$5S&MgH;W*4vIV%WH7kKR$JEkJ!>HvrRtkh#0wk+}PZ-`&l>6a46@A*aUm zmxYQ+0-st%!-H>?6dfoHVQBODu#tK4VbO@J-TIxJ+%bvKW*On3v75 zaPpgd_GI(?S2Jwc7yI4)evC1#?R+cy?g@#B4W(P4wt`Cokei`=ko#c(6b8(|Jd+I* zAj1C)QkP0((DE5fJKPeW0L(tP9FTz=<{)uU-e!Q=4=i(=!F-TjU|9xbGZ5#d;vF=0 z6Ugnb@EUAxqa?i0;{-Y4NQpymn4s00u=oYZ5u3k=&s(qrg2-dY?ggc5a^s11VM3Xk zko`xkcw$gDnQ)R(PDl9{UrvVko924KFH`bfp4+6b+hmFV^fN!MLxVZxKM=s;5kv#I z|DbZPd;u>q+M9z|lpRiMWYES-Vv$5oCH=_Ugjy9wlW zSa`wH=OA$#N;yKJn?UUhYQ!OWIRcJ!PQRxPq5+!RUP~9R5c|^n>-q;L%cYLVi`UsV zL^_twJ_t=2=ye@(+JS{RsC@_q1lyB9RZPD=G(hVWs4fJBY&cXDCH#mqA6Azl42Bzq zA%r#U(7+x_{DBcHNCHSqxZgm2LI$wBjGhiadSP)0%I9FSsNH4RnGvnr7m|^84Sdsbv!d-@LH`suFH%Xm}9uHnO0? zz)9lBjK^pFtHL-%ZI+ZRW|zM1x`1t_Qq8TOtn0rz^ZYsYC(M>{r(I ziGz`+(51J+6B|}}FW#K3wr%FDtNS8edE2b%Sgm<+#fOvneA6ze+}omkHqlW0Sk_DD zn6Hj8vGu9%9B+8_Ex*#cjDMA}rKHq?p1u9+8utHPFZQ}RAj!mWfySCzx7E?nJZ%4c zw(&IG{%F(P&tueaYMH|BZr*bti+nV`*-V|Yqv^QFVg}KcT;2!UHZM;BxtRI*x$JXb zzkqlQ45vV%DGWZ|4j?*r!G)HFZxSbL3oG*8&kb5<=%84?*s7BG;ZM8mTNEw`P3M`- z|8Q%!y!t|upX>BbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}OV5Mj#1$GMrzV;ccXvVY#s18P`TOIuCFD-F#FX;KD)^X0Qn{Siyp{up4>-Zo4tStT4yL?mA z39i@kkACf%({S$K>dx)yCmO>dLhmZ_)Z{%YoL3|9kOOEQI9#TC>aFB-nl5hRJ27pJ z>Z^l?-GkR}W&Sel<`ZtSHungl|!~!Vk?GmM*Qq|2gj^-AX^3x%A%h4Y#Mo?1(cx zsJ~M)VkR&5JO1Exn-ywa`UF06{k?nvzr{QXzmr^gu20D$=m)T6TXya2~KlU z%##uRA6?(~iNWFTyG;eg`ywZquKdQY!;{3xarFL;?A;UPUUx4%C{W$9;r>x+Np+R| z1-c-2fx|EQ^3K_R&)x2yCS4-q%fYC*IKlJu6)$5S&MgH;W*4vI0*9YyOEyqFEbKtE zguii+iGO}XYLKgUMWCCRQK^B8cUHQsEt)!py)}|MYVB3IQ+I!#Vp+p>a7xNC#|91i z^N$0(mOc2=p9)eR?CK1p7#Ik;1*pb))+w-BAi)TBA23WG|LzkIX;_`3mh^X(>x4Rs z!yQxCE&p`dWXG0O_E+X|o$)*Ihc&EB-*RsqbBb^ICkKJE@9s_WJnHv$Pj~4n*STy! zvzXmx^JV{d)EqCbGt*ORqjZZV&&mxGdE1TSPrbhN?%4VRP)k$(0|CfxD4!9?{Rd@( z!jlL1n^Kfa4F&gOn8vF#CaJcn4ID5mYw9 z)DcmR0Nr%$42|6cayu-%2AkU`2`^CDON}@LhY3Xd2O zw|{S#_btEgq$#}9NHAHI-11f)s0@ZH-CW8queJ~nJqC)XI5$12=U=||9d{7w* zFO!I_=aKZl+zz6#xSt`QCezi?#bC#b^B+BgH@}D|Z0Xy;?VQ&&OX%vlwf4WZK=q^N zV`QUXWhba!1_NU1PNrWU8i0O->w)P7(a45F#ZkhUNb_Y#Fdu9FqJce>_yZ$YkOYvJ s@Q@@WufXCE)LsCaMeVi{*i{=B?a@05W+A&57A7>Y7u-g}ZZABb022e_kddX?>L5-&(!7q(jE`hM$< zmA|~6ZUfnrwCLm{h>Z-4Ao^-i=FOyl@1D8rvmd=M6*7DO|Hb7wdTjewZ*-Cu|C25Q zRN|2Acd{fnW5)t@=cs^L1&yCi|Fyp7vDl&SU;d@(X^|;7llJ;@=t0@)FvjYpBypWpx+j@0oQcA_G zL!19)XNW(1yk^tyq&p86FPOpW*v6OT)LQv^>x}rk4Hpp%1>|Dptl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pUz19L6Ab5sE9I z5*8q40;#=t%}!*~&hra>woF}jbLp{?J5!r3RsB)fdBW)XL;gg@6b61L2L^7%RY0Ya zffyWbKpGu@#KCd`wHLE>EQ~#x^cv;9uR1SsaYk1@Lr77`Wjndtwy+0tU>e1GCF}oW zoHw)KT2^t|>*JFPmKz+muZ^_MXifO$#lP-2P@T9(*$bF*Ca_z8>EY^($IeevR(d9x z-Zy1v_~B72<#UU*{8fQ%PVbS^KKqybe0%Eh-u8nRwLd)l`P!@e@MiZf|ATXL+P-`e zf7;-=js@xlhvSDYuWmUJWumw|=ex`K2KN-*#od1@ibC!kcIeRi?{EM8v`AFhX#<(( zci-taNFGGjWeO?!S zN=NXH&%MmQ8glc%;V0UX3sjFBcF1goT$AVXHL`E(6bgw4yIibt zy{92wYPATb)Wd&@8>&o<_iF7kJ}{Sii)F8C+%Dgo8|*-{z;gA+EZ!A zy{n!n^8*gw_p=DG+9xsP^S)+Z2FA7pKx?-$FnxCe*$>2U0L;^CfgF}Qe$HYh2mJ0m zxp+}huSz;crdY+c@!pZHd)aj#?=b3l%r0E1NV;|kUbCWr_Z2G*|+VHy~rZgp7T^_Y)~lf6>xYn%G!qF4@& z8<`dv6W;T=Jd5K0b7GGU`ya{c)^+7Sx(|7pc{@ndPvjMk5)5vSc+^qmm{w)CaL z#6MZ426MN+eig*=HJlw(euDtEH2M!B1rKwWS_UG@0tWW=*Umu8gHoV5tWdMS6q#uh zY(LO{y->4I!kkDqWzg77SkveraT_J!1uE025rgWTD1Ilx{8{^Zv`8@@RL{ff zO``iLNP3X{fW`d`&r<_iT=)*}fA#&!Dlz+8@4MP|ZkuDj;7ov+oK}UG45*$10V47- zBAf~KLty1b>ZjyN1C(x#UD)vsuF&=`O439x2B5e zr?09sys67M9HFC;>B*5>ktlj~eZfz0&NI8x%>s4|k$05$cD!2~ou2qes#z@a?9}}(ooa@O{crXug-2xcUHm_zyNZ`LyHjSd zma6~a&-pjmmDVIK|2#vSfx|deUg3M4iSWTcaYm}9g=Kr%1S=)4Kl*s_d$qos|L-qf zcF(*1{+yQopQ#shtnKakw|Dw5`pO8fEIgkV@Lpj=-dStS{lAdoUkpd$a_CGXq};hV*O&PO6G?@?Y3`GxF9s0XEy)C zt=;nK3r&8m(?6B)Y)e`D%0FAm|DUtaonLS>$vnJA!$ha|=O>1ge}7YhVj8$)PtQqg zQFfSpt@vgJf4R%U>#5IHDRnKJ`lhMGNF?y&WYtr~SGB^slsq1@M?c;MaT5arp|}F7 zV*z3&kb1FR$@)JT=gn-mmQ|eg`uOC6+>FQW-_h3)fkv$vzFP~2OYJWtNm8oP}-I^VVn(ecMO)jsr z*e+nRw!m#VbN_?ag_r(jZ~)B$`ys_Y@F`Py9N)2OPo*9Au6m}-4>)|^&mzQXpTv~U z`#HssZT(>m_I(RNYJ4%jItZY&F9<>yjCF*lXGzoBYgb>6+s+1fHC~zbxYh z&^#u`5KosNAOi-{PhCr{n8jDxyY*MT-sC6_w^Jn+ugfz8ER5G_&0Ku#GfMPhIHdF#ES~mC>##vL{0)$nJD|Fok(JpL}2uJX~^3p3m3FzO7RzBp&Q?vC5I3 zbJljxic;Sr@}HZUH+(54CZC+)ez0QG-4#28)|AM5Rb5+B{A21RCpi&btF2rR_5>4+)|^hhq}IPj9`h2&s3ULQQRlDr2E8$fStk< z+pey1&CblV^LxB&v$vXcY0!p911FiO;paekoyE3RGe<0Z``-W3q5;Y+p=a8QeJC;tz~qK@vb>!a@m>Z{a+U-#`HBKeRd*Bu9zgG3-YY zKw^Sj03yI;3Y>?}Z6wBr*2*SWykpplB!I+(yMkCZ!NU-wlju4Q$sceVfedU8Nm;PP z@o<9Y%jMVG)7J5QUTwSA)-hwVr!2qdA*HSxNA#ikQ~m=1k`atRF1Stwiowz{sD1_m zBFa`VjagF;0bK;D58Z&8c%fRs6p}lUm~a)i!VYXdFs)63szgcuM7k-C#%=<+9Tr~j zygx|XMoD;q+BDRNLvWZNl^5Ws^gGEH89viQIzJ}LQMm7X`oH93(Z2Pi{M|B~1@0M) z3SdRRdIL)u{RfqUg*iNp64AzBU|)YN1KQ3g1DeAMH4983B}^nHTm@Nalt?$R(AZ5_ z)94^^8%i1_(M_PXA~oU=YZ`szz4PYXME1;S4(D3WecNKa{LlUZcji?o{|(IEm~NGT zr4f?aHU!&yKo5cYG-S4Ih%-M0R>#2;H;e)E6pRm~v8Ejw*n^S|NHibA*+>FNOt`Ob z9i2_P{^4lk6p4blA)B!9qd1TwHW1SSsv D5wlI^ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410160 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410160 deleted file mode 100644 index 048e5e4c93189dfda55507c10b22771c6ecd9767..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4644 zcmZQzfPe;`C*PVCx{SqEeytVKI&m<3-tyHmyi%@wSevi;p34@bNZ3nZl_iVl*3t^) zbwYoC>XtXlSZywLUHCcwk>;#^@ki4OHPWuMO-i#V(VZ`PdeZ+t*I&Jgywp8q@AsJB zZ~JbBd4LQ_T6A&_hz0^i5V18@VAJke4Zo`gtlXDA+&bYTe|U4KyUdY*>U~Wtmu$L$ zN*uTY-n}^b(D*^rmq`|GGBS*PdS~ONKI47lxO&~qNt4bri#cBSI6-Ym^NPpyGxlk) z-95eKefZMklIh_#VWG|}F}zg^*cC3->^`T#^y%{{4%@#~4GwZAA4z{+r8;3}@r`H| z@1==5AGKc0_hXuHv%2NdX_=&0-edDP+W&vH*ww5UyMRHorGWRrw#~~^KrUuJelGj6 z28aa#r$C}93_jitAUb!!g_eeI5+`g6EArmY4O(aDpjf}ys*?HPPrL0~6fOu&=b6p_ zaBH```a+YR>-0}0Jlj&%zVgqO^8e>7bmte`OfnDe(J;~J{rQO@<=@}bpqK_O+0%0p zTa+DUUn{R5o738X&7KkzA2c^u!dYEPvd_pW-T%nvwx-_Ih%YM;cE&-h%<&K}Tn8^XZdrvN2l+>$|&XFlrv2FR7>3(TfjhCCk3sE0CMG}us2H3kB8@Nwga!rpxPtY92_oX2f!W>q08|Gf)U6H?KGH9lG7lWxIq&~M z$Idegy&P;M#T9a+wh1)N+`{=PRf2Tj=#4n7|OiT{js+i{l`OBU= z$;%Hk4;(Htdz;tH5mh?OkZrub?=KD$eLT$z_82j#-C}mmZtK5_T8>i2gg0ruMZ6{KY+~z#%=yI*&SzEUq)QK zDOaU(X$A+cnaad1zv?u9R*SRmvQe_W!1CH6e)ZyV+bLf)!mOjU{Iwoi{Sjrf>MeM= zvLeY86t^s0y!S3$ZqE^2Sdz2SXnH9JYC=xma7%#VF#EvfLJ4rVBMC5r*^vANDx0Q5 z8ZnJoQ{sS05L5@c12yqN zwSp<6go(t2s~{_l66dDLKtIvcO<2?DAaNT?8YR(9pmq#3;t*>ZwLTh~KUexg^GvsZ z?;$2P4kbn(`B(V+`jPXpZn^Kw7eqi)2B_T#0KHSN&A9!mUy5iCdoNKCk|aOGw6bO6!|i$i$XPNLs2 z>_-wnVv^xD^5Y%ZUU0h;NdSpSvYQyry7N4K!K=E}S|&*$MDBET_sIk1egF8gq?xAt zy&JOeFw{i!JOj4~$bf}6yj&;P9s_EUJ)6ovLYhWNYs8tKGKU27vE~^X*h7gwFya|W z0Er2Y8dCBMsQm_NKf?12iGIhhA4vd-Nru} PAnAeI2xMS$2uvOTGRH)Z diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410161 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410161 deleted file mode 100644 index 0904b1bce9751d64d0d7f18eefc12cc5b3bf9e37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7296 zcmd5>3piBU7e8aX38_3PZyBjv@(7ojJToC9rCaKcT!m5-lDS?rbU&0H^poDX zN{?G)l$4A|AyI$aic+Ko|9#G!GxrdG)0OYDzi*s%_E~HHetWI8_g?3KAWq{?DRgx` zS3+v zcs}jQ-Zr;W)C`h7BD*(mu-jeBcKO@5-_IHNP--31sTa>rEpqQUf2^hhM)F82OXDCy z1o&FL!@JJIvDbF1(5aVg2GWL|gKbrb+JZN;E}JXKvNz2JDrD<5XAbv+117^G^)T~~Km`WG?N#!aq*F4R5mbF5Wcn1y_0BbgOd z5PI58K|6b}_->*xG$WEWbP zwJd%PQ?FXfB}R2wi_p530uCn#8Y@;nPZ0e0V13=cmlBU(Qh9Kce~xd5dXJ}wn1yPz zovNR$Us;*K!D+fc#S@Z}DTg4|`bBXJ8+26!k}@|GsuL(SfX`4nQC0WOGr+<(B-UjliUU%GNYA5qP8 zZnU+A^@97(+S%FfLIVwhi)wWQHmWKJRX;p+Fu?(}Lu`4#6T{&FQ;2}_Ae#v;w2Cli zgt|bQaV?sMMCw0HRsPLJm_PFUnZ!e>xo2i}gv%r*|1rO|ap%F^H=m{lmk8NVw|Cw? z=J)<~Ww5#k7z@dT1!u!);W{?D3!0|i@;SXT0=n){%RU-vY@oz0eilX&fF#YyU_ESy zvB3{(u#DV~X%9gHm=S6N=JbCX0l@|P0EK<;KB<{@LS9tUGMrafnE5ms7RAf^w*US#GrWEM(a z2vDNXS!et|A9-S~IDLvqzNp=5H{Uksa$1r0Jro7_5#a#lYj6K%g+W%)9e{ehKdsMJHr~-(Q4~cv0zqPh5K(I{L=5x*Hu$)5NdbX~ z-oWF+jn7%E6%ocBpQCTMI2;xbKdxG7i8x1CA&H#l6LolT^4jvAl#uGu8}-7nHG}Ovs=Ppdx6JxUOVqZ;px=)@}T!(VOv?o6j z^B40q$Z&_e$ejrTg<(a%+*(f^c(7NsR4%--f?s()XKX+dcTvrpV3)im22uxv)=9uq1ewTd3R@;1Q<{-ZC_rKcpxD; zI;M7^{_bkSQo4M~zAcC6P-3N%b5u5EprD?EpaB{4BLUnFpwHlV5YfF8>Ehwsg@i6v zr=Vx=E?|V;JGmgBAHze&MgJi2$8~VlFK6$D>##)h83C?uFg+eQnNBb#m^uC%9S~37?_4hSZc^#@cvii?(#-nyxZaqawebX(2x!(6D&m&76nE7^z}` zjO7ge{Kb5(g6cv%)FiUY{KY|?j?_WTm>qV-KyY~2BltR6jw1LTX{G(B@(`c%#tEEh z6U%AD9GxWG#^bM-_yEE3zl`DV9EFF$@{7Bsztdk6#|^g!P7+R#PIW1<=d%1AJHlt< z&1ZJFhTkxd6LI?>R%fJkpu_mo0yIv;*E4>9!Tb%^>qz6FK8N_ebVcCLDa;nW;&K7& z9+GQ3jz9Z5#)s#C&4Zga6M!?Gd3@s*TnA3XTsG>y$J3hm&bfbskL$pR|AHHC&5VN+ za{l0m;Kc9d1O=oSeO(*dpm@(GKWT86Xn3D++=h*vq-SmFin4`e<;XV!FzQHk+7}cJ z%Qfzr;i0CL(L5Os?2$See#yYzSCAob6T*oo+URE>fC{6B8DU8Zhjf7eXF*sIXhh|GUM)%xd!qz3BDcz)1|LO zK3eu+xjq{2;WY{TO%-ccj&8#`c=(|NG+_{0}<4brJvo diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410162 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410162 deleted file mode 100644 index a8a09edf7b5c752ccc66d008751f2cb9ab568e92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7176 zcmd5=2|QKVA3x6$vL>pjhI-XRcHXnaM3FRhSwb66Q9}%Rme63L#ozK;kSK~?Go!`G5NAx#Mv038lx>x#3Xrk)1MaY=8b*rt-gNM zlo_2Onx@vT(`hH@b(y~%w+T5|kiX?+KOW6`Frtsiwc5sQdKF=TjD_uU@zIMUsB3a`)PsLXHizW0PAp1-Y6!Dk?qp zy|r@8?~e+zIwX6iHiz2+`M94XADlS0kAV;iUaMMjPYCrmtsIRqfYlEs=<2uUM%;$Z z38lt?q5dy-I~>+BnHrsI7$(@%{r$<~Q*Oxal-MQR#NMJfb1$v?utxdv*5m8q5A+^q zeyGw{%MQ5bspqm)iKd#^-3}P<`@9`IHjMuEdgh9_X(qesg6{c9GtHXrc()c%H}Bp4 zEGAf6&c2K_qg)v2OX*)LHD=0Wt6X5PE`Pg23%fqCJm&>M= zOm=$E0#fyK0)rWmtEbw>SIf1gfxfMI`(0vHN)0YXCuOthqa$U~glQtH*1sO_Ee7>r zei;%oW#b;WO*RndS_sz+@JrbRI3{!^^SMINxrM(rWl5xK&=?)&mq&Fp(swo&ss0#z zGKJ=iujAE6nA{WNTg+#6#>y^YQC^hdIm*UYS*?b72d|~cJgjca_qhvo3Yadkv~hqP zqVeKOik2E7PQhbhqVYgQu2S&tHY=gX3YUFZidMUs$}6Qx6zZ9p%MwJd)TJM)x2Adh z;E|N@YAs#p=km_<+1`Jp)Hr7>)R^D(I)m%W^u*YMnex<264v?kwW&6hlbDTpOXJ%^ z%UJuEqhxRN0O`3V@Htxx0bstzfuQ|jdmeH<0Hctsqxn2+sak$?V6>)%mRh6S`PIAE zZ2%=UcYAk48qgJc&o)HO6b46gPOD$Rt-y5{2AFG3>~R%;Co*wDcB-3|cJ5P|?}Av{ zbT+?sU)A@}HFWWndZy1R-A>2b@@MA#B5xF`E3Zxkdy_qdv*WK-Ef>kZA^|mG_)q_= zamQ`b7B^t@2Sb{A-}>~at}x{#F{hYfR+THf98Cb2DFe+`1M!IQa1FLc0u9WOm+&$C znbOtN|Pz{tF?`U>2+*DdDs4!^Jy&k+UlE9AEK_Oa5=mgUmVVxYOb|xXPxwB`H`?>btGwd&DFJ~7xg#0nb(xsgl=YA<5;aZ|NdcK5@ z0`;10)NK7%!HdPk3iZ4F^qggmWtbBaFZSQkOeT_<%uN1Vv@RCiGRgW9x-Y2 z8PlK~9U<8Iar6r@p_*Y`D>02{PP<{sf2zS`Fd6!?_=e*5QBz1`OQwrEN;w)@ZTpI`PLxk`M>J}7XH z4O8@>8PT8YbQfiBtd2zJ=sZZ~1E!NSK8h;IZ zcaVenB{3ZME=6mJ_@X&X7Z3g-&UawQ?*uqmNZ$)kUL;z-x||2Qkk?!e@y{ouv%S8&a3p{wJTcfpG$#?eSo z#Wizcil5i@CpqYOwqwj&za?k-E4w{5uBs?j!#`n_qat^y1YZ z`DHjU4Vqs@2)2It0Pk>vbB_~gH^OFoYi ld*vqZ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410163 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410163 deleted file mode 100644 index 67783f0c097567624047aac8693f24b3ce1624bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4700 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 TB)SRIXQoCRVojsaG{^t|*4tNU diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410170 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410170 deleted file mode 100644 index bc33e9d5e459ac5486407b67174c370e3cfc1e6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3876 zcmZQzfPe^dj?~#d_qXQ%QC$_9xy3xrJ{m8Vk@T#ZzfeSpY>nyGs_se&zb)0irKiBEblaf0e$HM=Z z2gltxcZuIAK~Ab-0}0Jlj&%zVgqO^8e>7bmte`OfnDe(J;~J{rQO@<=@}bpqK_O+0%0p zTa+DUUn{X?C;38cPO_3Y~JcQ=rqyNgn{45fq`3b6;SD9 zAO^=9kVXd}aj={~?Zs>z3uBKay+*n3tImsDoY9rf5K4K&EuSqvp#hBazsuTApdjV6<1a=EBJxr_FSAOyqH&@|+K_2~-mQI0eQlrET$$)@BG`Rax6gE^*k6sW3sRr&|9NCLkB*J1 z+Ih7!cBmU1qOxB8c;;bhz3MUd?m*e43LS~+{*hnv_vijSvMtxd{=%e{OB*d7t-q*K z)L>_+x8rGAl$unVO2eDkmlAv>Q^8399DX8)QYMSLHYHyuBtOH6Vxkv)z)N+V!jEyqDYQbH~5_PvEkh9qt82 zYB?Z1vS(AFS{WF@<^sdweXvR6hIavZ6F0@)~TPg->9Csd5Hpt!)w*x1Cv2q*v* zgVQPgflryr8GwG zSIpuo?cMq-UvF|0huf(Vi`V5D0v5*Wv}P{8_8F{d#!!v2M_m<`x?Q5Jb|5@=nVJXy3aH#-fql5`m z4ivV`45GOgpnSr44XDuSj>Z*eewzf-2cwZJL1MyWA#n-kLGm~Q%>JZBLEE8njG!_N zrjB6#2Py=*ses0A0)-Vcyat`yCQR1mH?DC}jb`b_uL~g;ah(%?DFhEI|oB;>>?O2f2JAU_REgLj!v# z@drk*APFEb;XcKcm(kM!NH45Bhvyp-{f=Qjk^mBu47VYbx5T(fYh@EG-ZAV&5?V|YgXs1%l0V=!0vXsG0+R;-*%Yp* diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410171 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410171 deleted file mode 100644 index 996be09a5357574c171f48275a4c98135b2216e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4908 zcmZQzfPjS6UU9P??CsgHdL>)&J*O3u%H&pPYP|iWIYaKdr4y$QP?d0mIY;X3pZi<$ z|ER7C&D>%hXL6{&KX<|}qsZrfbkem0m$Z0CHun5xdC)Vf@a@{o>6T(ECu~rj9;5lv zVPI9O#g9|&te+D2EbLRBxxI7Dx&`@3zaI&`eRRgmMrZCNSB1%IR=le8cH1tY$@R>6kq1iBW8M3^X53k>#@S?WNjkY*UUcj3rVs|vmTKMy+cqyx0lAp@__+hF zFF-5^I0X_-Ves*G0MWS%F0?d!lQ>~pSdsUBZqPbI2gUluR+Y>Tf7)%|qHsZII?rtW zhg-Yl)fbxlT&I63;n|k5_LYCOl>a|xp*z3eW|Db$kA{g(@6S&RDgXYa2E{aR$)28* z*rMz(`&#kM4E}PLhu2e|ty1b*IQ30aiIGU)$;qmxjIU~icPV*1W{-Zn4dNyS210QK zRL26uOd$0xcbqRzF&3|suIJT1{N&l&Q#tOQ;?o67_g|B4u!=Fc#lY|601SgFpi*$0 zf%E_YGMk}p*7wkbA-_I2O`q*?s(R1Aj~z;{3LS%Wf2i4CELkuo8>B(@Y$}KX0Y*HiuV<|e?%8r_O^hVV)+^=tew-Ub?_6rhn5E8obKm1f7MuC*sr}|GhlO!>U8*%zpVDIhc`z{eG$8APU^x|Uoqi?6hI>#uyh z$x$3`r%EhdmuCoA7_ZZsx%k>=kQ%069~wY35HLdB>hNwJ4@0x$`j8gUl5po5jVBZA z9k)$+^RDmBKC!929=t~Fb8ImIK!zBzhI68GVf&9-r%cn8P*?KKgp0Xf{C?UwA+u3t6hz1&WpJO1^5 z0+;RVa4#@Y%ONITPfVV|(77^G&wRuGjsux-mb^5W}GDZCGzNo89Qz~Tf-Z% zQ_S_j|4Sd{9m-f36f~b;d*yTI{nr?Up!!M5lLXt&3=HBPWx(zN znR${p^Pf|kCuv|0N}eRqe2nNr56SiEC|36cO3ljQJ1 z$&*C)@sRuhw-Ly|=8%^hZQnPZIdSXxtP9i2+gXnGM(3Z-o3N1gf$YcGiAk-Xej5m+ zK-+jQBN&m|b)dLMsV9l(3o@{;zq|(8AFKuHX9ZaT129W~d?Y4J7Sgtc^AK%0a6Jud n2V8{8p`?Ez-Q+=IH({-h2Z`G#2`^Beo*Hq8UWX$^GXnzvm1dWs diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410172 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410172 deleted file mode 100644 index 98d8c4e6a57dd4c5a6621440c30bcb2fc2025c0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3924 zcmZQzfPlT)vCgW(bz83UD|;Vyn#OElVZ!em8pIU%L(Q=DhUzS!D&d6HUU9P??CsgH zdL>)&J*O3u%H&pPYP|iWIYaKdr4y%5(ai$UT+XcwD|tQ~I)3_Ny~Ar0rS$Jhx@E6> zZhXo3Ga6)5(xQ`hAT}~Eg6OTW0-JW%YWQ6}VCBB_;noQ!`NNw--DQphRPSqIxn$D~ zRO0ZJzj(*HeA~XSA`yyrIbGv-TKPCRX<2A{l*h5|KJ8=2b0#MF%7<9~?ZWfE%)Kn% zrTl)+Uq3Z1JuQb@SIYHQvvbxQyq3l9E*&G7<@a}GPh{xAqQceD@-4>YllwGH`~w8n zS=a0~nfvun=;0J+*QjMiW*M`DrtB?PFBSjxX@GGTgJ??)?}Kfdm#2VS%zXUZ0e2A) z3j$7oL{k`iyd6Mv?t%*~4c{bA*cMjgy`LMj&d@=zez8?0^TVHZ+qWoO5Sq?2oB!d~ zZh7^ECO_BdpGtVPrL2ABpDpG8&spfsFSwax9^Rv2qSO2H6GO_szo|hn4P3IP=Onf$ zJIuaTd^3Z;+~wi*)Mu-dx)x4-(^O(45_od5>M7%^TH#$v9*^0hA8&)WiGhJoTmjWF z12Gdwz2R#|<{29l&rD-c&3>iwErpZYS*g=UDbF+SVa%< zyn*zAK+>YqtUwAR##vBYU}bDkTmDN}hI-?3^>r5*RKdZx?|IDFsF zBE)K+#FWqbntg%lnF2zC0(@M-dcj2cscXph4DJA znTxM|1}S1nih^ligu2zCJ>&82l@2$a+=_L_*)fE@16c1w0@*RPuM zUT&w)9sl}2fy;JwxEC0yJ`NwD=^_>@rHGqsO*cXBE_uUPb=$sf}dyd~1+sPmOibNucu{Os0wR>vHLM4g9Q zEGPX~%W}_^7ibpPzjd>|hb|2H^}%WSY>!jbd;WdwPUb!D`rm^OVOOzf%(JpEJV{>1|{XDtzpyk1n(eq~+vzW){djJ1kb8MdY1ijO$ z3tyxd#kO{yT)5T!CFlD9P+DfbvFF;^8K1WNeK`5g{M8IE;+7udoiP1B+smWP%68Tb zOIV2aVkXayu-%2AkU`2`}_GL5?_5;t(7rX!RW^or2;Q zBnLK&h`1!ad;l8`BoO5UvU@@4n%sDzU6@ejCS?CnE1nouFmS!zntDH)`DeruO?KV0 z?=E&cnzzvN?t?#*Y%Xx|O@Rh;%6}k$#UqFYa{oc)VEF=Gju27DGO(||>;bK3>wxBf z>Qy*E@+cA$E{z^Puyh8tA6Gd-oSQB^p|P7lZij^zJbexlx1p3HB)SRIR-#56qL(A! zNaqykOzgg4c3ELX_41#a&TKs4<&x=f{lee*>|Mgno@xBhl!0E?L50B-EX?6)lwkc2 z)Fyj26<$9f8wO%yNth_%N1XX7bAaU(+)c=KU@;$S+M$6xl=uU~*+>FNOt?=$enJMY zyo{a>KzhOL9^`VJM89L$k0gM^ggb|Lw;`45#JCCCh62SqhP_AvNKBI51gm$!8i{VF OBKZSuBQ{4ONdf?bpsJYw diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410173 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410173 deleted file mode 100644 index bed9cbede3892e4c6a865e90700b56a1546629fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 zcmZQzfPjgQvoF8QXMKCU&Pz0XJ;(AXD|r4t%H-kL*vs?dsm7$WKvlwfwPT%Ch3mFl z=U4VV>@kZXeDn9Auf{VZRU(P<)a_qXHh zIRAb>(Gz4-(xQ_OAvQ8Fg6I`0XC?N`EoJl7oE06tW{LITRr*Gm7NWL2`m?v5&i!Bv zRO0X~>*Fmmxs7V;F3-!fAIcyr3*EMQt|1Q=N%YCTWWb9Y}>p%1>|Dptl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!$knLz3%CQo7LT$!n7zTtnzfy_9|U0d&`HrWP?PJ47_YVU#kYzBTOP#9DLm4f38 zN=pQ!>iZOFSCqQAI=h%vI68)wl_!^`+uEY3W4OI0A~hg~`?KAWo!a%Q=De5N>2t@w z{!ietogMB4Mrt`A^}(*rK#B;r0M%H}It5k>BpAW&1E!JVN6vqXJIkY7Qj#na*^+d; zYHIx3SxX<;nFn?S9CTs!*wxLER9pJNdJkjFpSq_)x&QtZyRUPOIG(eKt4v4x94H*X zVPW{%k$J`j#WT}bRI^{Hd`scvc2?^2QOfhoJ9*M{g0LY_T?&JM*l7j^jRuhYKnw>- zi%xR^IUq64g5m-zV`CFDONcB?9hgq>4}8j09>;gA+EZ!Ay{n!n^8*gw_p=DG+9xsP z^S)+ZpcbZp(4YVxSBPd1nSSb8a>XpZ(%!AV^7ST1ak!l-v3OmcAz)#=PHX1kYo9@C znARE-@o4CX4lUd9SX0zi3!xg|2A z-{IZfO}Y_l)^eI#es%3t*OXh#GEd)ijZ0aUQX|w>aA^Q?Gn5abL0nK6FhlbUSejrS z18Ms8p#fPBSR<4`HXJSlESF$vh%{e@1oJ_Dfcb-#_Amn7M6UT5!Ga`!#Ds+sBrU^v zkTQ?~WQb1&~w(Bi!3uWf>UG*3&g6~BH-^`4#)SP`h6 zh5%Ta0o5-s01I<)8UYCsQ9m(AT`GZifJN}QXDcRWh1kn* fP`iWNc%ogHQ069-_(0+yF=2s%Gq0h?6I=rTdWh8b diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410174 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410174 deleted file mode 100644 index 395f0a84e345462bf2db5c4d58d5d2bdf0638089..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4704 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410176 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410176 deleted file mode 100644 index b0e4cf4dee13c8e2a5b02be14762967771b72ca0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6248 zcmd5=3p`X?7e6z4kn!k2ggl~DQZl+8VLU^)V$he$qY;u6{{ zr6jl8%cNVlBy~v*z1)x_Bkp(han9T`eSD^`{C=(9Z)UHv_kXYTKWneG_c;fGMrFCi zs#PZ8^sXBBn1Veorj{)+TBatv;?pppcIlY|a{iZK)a(q`zs|adD5akyyk1$HCDUP9 zF)Kr_RbIwB;G?eRvGmrDT6%)?^{EBxZf;mCA-bQj7QonjX458#nJa$#vUebTL zOgD_mYBn+(%6&DTNuT-nSx7jPSF>EC@}|Xwr-^^uQ5RLXo>)};`s zoNF`fVV7L%MX3^}g_$Rn6$_d#T9tamO=&c3*qguO$-x$um>YAEe6;4jnsV1056^3M z8GJG0Nl=6#yJG=yk&fsJRsbXs&k%W9R&tgG7z^C~z1oHfv{7M!UK(V*mI7M8(+}bq zAEfT+2kr9jK4D*|K~dbDqZ=mBK4|busltO{Q?*j~|>5sFKx^2H!!nkzr5!jf@#`caOWrFQ8;L1wZl@qnoxr^z1yRv@h#O zS8T}2IqPatRalyhOPu#9Sv;Ta^1N)669i4PRxoZV{38OqGxP+xisCYxg~pR`hv9X5lGCK0tqWJU}y^bL)Hy$KNrxCjEP6p`KoDaTEwcy%pW*+ ze@ysPf9-)yWgCifo4wTxI~*2ktdxGpB=59% z1>@#ggucY!M1%{R4~==wR~}RxSykjhE6Flbyhuzu;yF?nEjSpnDyH0~cbdO-*d3)> z2bZFxhaoD}7ZTsP$DBVSTPUtsBwg7NqDn$JP)@|$Fi43jbj#^A`t`0}UfQPA zTMfOIz4tS%&EB@?MFnLUbWE2!_0iaxDoGu@ekK1!wdMjwu(fOHl5n`2$Tz*hFcswUWQ3e@%_nq1hTRjs}TK-i095I9TV2pGWpxDYQ>0FgQ?G zQ_>Ta>0j*2%LHMeyAb;x;yh0Ci{m;_H;Fj8p$ z7v)upf|RXj!D?N>zD@gPCHoe1?^JII+IrIcXHuQUfUD*e*d|Y2Aza|R%8eSC*8RcA z^{Mf?-=rzcK0^%_y6##kn`4KG?ZtaN&3Br<6Vorw?qHkS9aHwYY#T&VH+z(voL(g7Q*t1C|a8@(&TF`Xz;LK?f#!6j=4|5jYsSH;yUgfVXf|?3^QMaMRQ*EpXFQ) zuec_c%+X}i$fDY1=Sn^Z#dSrHV17tmIcWUQk*pdJvz{7ob*O1t<+H0J%H&(F4yE&M zpS$arAc(|IB0dtsqp_0G@n5Rrzs)R!?zq<4%84AZ#>&{n-%DQ~9fzCISVw0JIA&2f zJ;p~fEm#qiBfW`AuY-&nmVI1kSQm2oxG%stn3(`PG$9ulqnE)#u<#!N;RnZ*PIXJz z;vvu6JVbgYDtP$(C8tw{Z26uTu>)+gnIc*5`%l#CtQPAkJ@5D`*ud1a_L#SzwhD)A zWBUG@IXihHHNf5M*Auv;cX9IyrcF(RP#$Yu${&6Fp$CX(c8+g5g6owRzm%y!ve zW&QYGpEdQDBdyF8(kUEi7B zZF%0!usxy?)zZ`+RxshCE~R!vwqS4qTHloZXE$ndMhXS8$^XtuuF zsvZ-DlLJ{Fuvdv-b3uza;Z?Z^q!zeWz&8-oKm0uL1|1`Sa~jq8<+OE@IRWliyuLSX zUlT7-W8Y#8k(l6~31PDkM6Y@K(ovhT(AHhCK{%{5yu;T?f>0roQYG7RI&Qvf1_AZoApgSDU+i+MDP;cNdQa(ZOp90L0(-WFm4*MU

!bTM_v)VfLYV${ zU83DcgT~Ddeij~;37-*Rn4Z=l2i*GyHWg`cfx)R<$T({{>fa;V{sfA|Vv1by$0@mc zk~snHSe`LZp3rx~?Q7x%p7nVIw{SR>3mIn(;~4<)SzUsf1@GXc(a0`c1xsY+zFrEPrN~+IPfuW5T>e)|Nw7F60 z2d*h@^(zH&gJrCDxslN!ZeDWV<@orP1x+uiD@VU)#lm*LcSNq>79OW^hsVnS#6O$^ uW4_Dr$%#72oB((51Lq3^ZV~xTxbfuj7jlY&Z{%C7Ap-;iSI6LzEB^ua!|s>> diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410177 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410177 deleted file mode 100644 index 794bec0f8a84eb857c9895cbb0ef3dcedf87a379..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7168 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410178 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410178 deleted file mode 100644 index 16fc67540660f379295b74e16b08ac0cafbb002f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5828 zcmd5=3piA1A3x*T)GTr-8$OrSx)jn(vtnfL$x&;RoK|K9&O^PYjA z*&*iATIhzv3i62pXY8o$J(hOTkCGBcIAl9-kOy&78p`5lI z4~s@?8V(TDM!k$f*WD2DZW(I!oT8(rGj;zv3)A~8elY>rgPIlJT;B*X zIVV^CKARCDfH_^YM)rQZx5$?o-`m?~UDq$Ysk8Bjo{T}bPFz9Nv0*Z7VwB-Ash2KG zY+%>rdj8Vpml^7;>Npdsa5ZX~x}rd1hX*m=tGw@@H*${1KI!Y!?xJ`!bA}lTO7$y> z?l2vpbHZ|8Ia{fEbklm7EgM?mR<3J)=R{4vBK>U#Rkg&;fBNZ3-(oHHM6uoLu0Wa{Y@nq>7GD^F`PdJ2 zA%PRJ6$YNZ?nCi5w{(q^15&7df?bn_ck`9%B%?`j;#~#j71fd`lecu(PJQ_&LNngw z`@FB!(@OMs;k;#ExH@Hh#N;SMpP6RZI0P&7YG(A^R0&JE zG7!w%C~aLCwU$k8)Py(1v`5swr*IY%1TC~zu$?gc5dijbg^|m1Kd*Od@sQEceY|t! z+wI+L#Uqmmv_k*NA;zxNkoYzun1dkL6xlQ20}s3mMUtgP{Y7;(?H)W|UCn@ON&|a1 z*{3R6?HeM3l^M|pE`h1xK*SUFMdHGH8+ftDqv4=mhNM(mV?XP{YSJ^qpM?l!H*?On zclD8bQwNh~$o7HtH1i_dpa@wpKW+A!lYGQdLZQEOoZbhHS8}6FHe?X%7uqA z`tmZjXkPg-Syha@$ad=VZ1FtP^^0ZSWs?|24nfl|YKsq0q-o zo`{ThY>MvATYr>!HqvENf#V4n)690;zydb@!)`k4`@NWVM8VW??WhCGcCwjzZ+u)O^vJg~V^f;OfE__s z3o|Dm^}$@qZ|=-$bC=d~gnA)*e>foPxn86D1eWze@==xqqkzqo65!Goj za57GE%Gh>uq3_J#cMbi6vjUu1g?&l_Jh*uc)I%xJ?qz z1fEJx&C-kbboiNYt_wjw!dAOgE#^eDm-VG^>#-xyet=2Xe{$uSng%^Lr@N;04w-7= z#__AHGE!pmc5G9>t#EK^6PgowV#6|42Z9$~uQol=e+{((ya=K-BdP^CLi}Gtcpo$t zGGWPZIs$APjIH^L596EN2h5E-&l4ZifYq^-c|N8N9@sbqPUMye>cI~|WP$Sd!8t+* zz6SR2&(_Y9AE&^HTsZt<>es+TYoou12M#j49O4o*srL54tIQF3SVMO z06WH4Fjmpu1lz~(1%8kJiakU)!96DsiWupV<}90%jlTDu7zSUGgItr|rAc3|D3KxF z3AjyJE06LxUyn|q*D%hxJ<7*9YL$BI3fK=hyII0e`1j1}=W!8WHy7l{d+zyFFoL^%1dM~!Smt5tu_b{*9v+9?iQ?tl6AryYZ? z+a3;B}X^ z^D%Ys(1KIoM2tnG9_|9E4Xn`KSm>TyWbHipaSEKsh4ZKGNq#VCW&~r;VxGJ>1x{Qv SCN77-lkfl57I9Bvi2e`CUuHu9 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410179 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410179 deleted file mode 100644 index 91f91e0338c6685da2475667ff4ab8c8cb9852d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4932 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 XEZ9}p^C~P%Xkst8?Tp=Cct8OF7+J`O diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410181 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410181 deleted file mode 100644 index e9e3eb84c82432be9791b07ce75fe406b4ded425..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2840 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410187 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410187 deleted file mode 100644 index f2df1e2779f1af5b9c617cb3a645837e8a9062ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5164 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

B2P zU%_|5guTnd|5tf!R$ual0M`FG(;ti6(B?FH&~*C)Y$vMg*NRsmx{!5ma2Wy zBqm?K+RbiqM|KzU!&3*Nn>-$#cTibe(fo;N%Dt!FUsvXG|kG6o|AR9Guds@=lG1jAM*XL?*9Gvsgz*7%}Jh_ zGTjkR&zsjY`D(j1Y_Mhnn#FSa_lnBhpTxY+{q2~1*!kBB8NR)>i>p66N6TFD{Crw` z2iQhX+(H0Kyh6o5;lKKxeq+L|e4 z!hFvuVJ>Gs3D!9_sfXk)-UQXosPi8PfE;*z3grHSO7h}h!_s&=R2>5`b?)M{NI_`5 zo(9y%3DXOrk=&2OgsZ?6reOPlX;2iZ5+z>{=ce$dGJw?Bv@tp!qyRbCF zh?HJoVGe2wg8>n34+i%2=M$jqj}D+FR;X4m1+xUmL1MyH;7X%l`+@$`f~rIbbK=}| z?hlRKgf)#061PzjUZ6H4HR2F!8jW1?UrKV~rS<9ATjY;%m1Q-W?lal;^3k>jH%r{Y z7dDweBhLI3Slx#(7|Oz8KGw8D1A8d(2Zpne z1dy0;@8ZhK=;;8Y7o*KXqTey>M-o6{lHoR_wgNG3lDbqP18wVK*o!29#3b2GC~Y31 R`zuKPfZGUUU~>pe9stQedNu$6 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410189 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410189 deleted file mode 100644 index d5fcee359b5f559a9376510bf95e124f2b049447..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7128 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 DG+}yq diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410192 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410192 deleted file mode 100644 index e6d5af2aa516f3fbc0eb79c1764e0deebd533c86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 zcmZQzfB@x=A9EY0-MOf6=GD>8w^{*FfoIn|dt2A7VLMslSh<2MP?d11)SBy-@otmX zg_ft^4nEE#<;tt;`ovr>Bl&xzNC)@I&nX>S_@7VRz_(dF)#|K`z3$|zH%qxP@60TH zQhIZL+3K%7U#Xw;pqzuTl8^WwX_XtqTi_tP*Ey#GalS%C+8m|0-#R`oq;m zY)PrN@6O>q!f|fR)-#JHgap2QvRg{VPnhFPu+lO0s7ve&qAe46A8gyaJO$)p=Huu7 zJrDu0Am9{8G=;&(+W|!9F1XOr@J-@`ZDB>;`?*2u3>_5f7h6>_Km2L8eT%{cq3Jxc z`5$iWmRDbB@^hX3sf1@+%Gy`{*;4-hoQ3ZEf}2U^;XN8AI=w$XF{J$an;I0;z$JTn zPGXC)!|ZFtH#7LlT^?RfeYQ%eYvI&4O(jMmfhQ-co-)3w72c)f@t8gO@ivH?7#Ik} z6;K@u5Ho?)pK5yS>#8y7A1CkguS;gNU(Y@3WzfYU`_fn{YVwzwBhC!`P7c5@=m#nV z#~DZu5FoP|x{k2FX5P17pW*a-YgXOD;_9!QMtNm=YiA^`|Gj5Y1uIAc)2|N=AQ}i5 z!R7+vwnjZZ=xdbC*Ap$<;}iWXH|z*sxnPNPwKT7*+m(y)*0cSa7nyxlxaXhe*tMi& z-k+O`F1%X3RY;*pOZND$?O$i{0nGyYVSW0N19Kmm*4o;>k7CRH_{e9Q(XN{F3!m)p z)D3Yc^6w(X5B+x)`YiO?<@a7yYhA37Z2y3xuY0|s@->Cu!6DrSx?umxo=pXN0OSX- zxj;WyE4;Y+IaB@7#fwLu&MW&inR%gaq_@GV%A|{n_s`!@T))3sou^n@?!IT!n!4Ze z+?o!JQf|{0s5PoBPfjXK+r|v@LyCXkQ>OAbzGKy%N;~dd^-P%`aQMETMTpfti7B7= zHTyC!wk-f!yOn|Idnm|$Acg~AzKR8MSnl{ai${u~4mjMdN?|-jycCiu*hrE^=G2B#XY!HRUSbC-mpZrm0;w+kd?&jjwzz zn<96lSWdBRjiL)%kc8adW43=l=?t763|~7k&)A@NW*UoX_A8ZdDV*HSN}WDRd7gPE zPnu2;HUz3mVGs~I&A_113uL2(<>_pw7-vCoft9hbiJ2u(04fHji3mTYfY6`-A6Kwm zFhNAPFfgrK>HyWj2z9H&C-I%`^^F3Zz1A)I2^$jT$1p4V9Q?qO#F3({y@^9Ib6V5E zIrHX}v{&07S|n9`&OT{lMsHryY2m$l-3r#!>azjOV-Y)C82In?eHkmmH=@s;WYsL< zyU4ZwWr4QSkFQ!A*3MCZ+L`hn2!L!@m@opl|DbZ9uw{mp1z;f}!kK}6{n-o9uPd8gU2?6QuS4IQm|D{!G4fU%gnVV#m>$erfw={?~j{{FpIv#ukm;Yv;av42@%K zY4jIV4i@I1`U(t)$fsf&GdY2E3Ak(x0czrfY6VkB2@{D4S3y=9CC*J8t7z;dtZ8(R zxD6$ZlISK-{YZ^C#F|ETZ#D_~ba7h7)jc<-%O)7A{8|}%WX8rn*)x_#Pwl>>@D7?X zz^z3f8&{e^DMtymUl_-wnVv^xD65XV=vI!RN81^CwATddH6DZxn z!-?p2Hj*B=jX(xAhfFft@0UnJ wM-o6{lHoR_v`mbfq%M`nK+9qbdyxc?m?XOiB~KFFe@F5M+(sY+n?qpo0Fx44m;e9( diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410193 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410193 deleted file mode 100644 index 02cbfec4d72a3ca47c808158688620d1d24dc42f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4884 zcmZQzfPhB~3OP5<#k_rEW44Nied)Vtk*_|i?^;^D=UZ0&+NTQJfU1O*JATYCln2B{21XFQLglQ)p1GxLzM8Y5qt`64KD_T$?f=SS^A^Yf_-berR^^(2CzBQa+MWNFka(#`f|AK-}Bq9%r`5KD%i$c zw*J`$i63P$`mtwiawQbAn9o!$+ z|F|u*b$?E(QGpR>@NUvM+YJiJH4M5p)XCx(=Ne^Y~E8n|Rn z&q-`ic9?yw_+|!wxy!@rsn1p^buFCwrm4h8B=F>9)lG($@YmRsX#R# zePF!=?Sra&X?wZ+O@OUtIA>il;|_aG+hdcTSuI_2e1^c2^Y@o!+yI)#Dd`$rZEsN_)5d%GaA5#o>0U#Nu^%hJc0fI<1+DuYCroV>Hx-DQ5)x517Vw{EL>3 z64bl!mt*RO#?QT5R-N>?aVYyzrDk1RPuR2f&q8X~C?uykvHaL`E2^dWd9L@Ay2C+d zRCd{}xl(`aU_Cd`KyX+ZzIJ4uu|e_7G#1tDS1R99IJupbI(?M#Jo8STG@T%92vnEC zARu;{fkC4W2o9J2y9#|4dhPOiud1~!)=0L0z|q&eUQzj) z!tdaaZUbFL27V_8U_P4wR1fnj$Sufh27@0xn*NKzGz&Na##r#LVr`!E!u!)d*_4Biy)9l!e0pql(S%`H z9hc6Lo2x`Wh3s*nzj=Gqqe!x5W%k#a=49*#I zkM^#e`5LHB+@tITOgR(SEkJ+s%PD^MZOq!rcqPi@WM;$`Pt9W6qg*LFL(V%Uonf{p z&HlJWU+QI}_^sUfcH{E~E(e45rkoGEQ}DVw@TVff3=XIp9F7Pd-YB?o%AQNE%Dsm_ zvi>yC4SDP{DPybjLo-h8`iKv{2d+;kdnmM)XM;p=NBWd@lifY9IeymuRAXJ+qZZW3 z26Pw;w~nlGyZ`qa)sI=z<{ZEC_3o|+$?8PAf5*Se@IUyZ-w1Vl%6}jLvSDGz2;}~P z%7Nm58Jb4GLPV4!Vj43!RsoFzm0h7gO}tREz!c09AP0#FR{@T5I1gku2td*(sN8dg z$}xiK2Pm6xS<1iwa+4d4-2`$wEW8Gr+b9VyQ2j%VI0T0YQdJ2bF|5`SO>3z7g56CRMb@-lil0O#1P}tG~vzv%KnR^*#7r}ZQsL<+}@goLET|Nn>4@M)o6Nw3vg|rpm zJb1kUu|H{1&@reSO8O_#O?5PO6V|*xNZdwAc!AnuC;%zqkeF~K>(b?ffh zHcXi$3RJ%VnCd}oUKD`EK`4GF!hAIg*;S;NkCKmxZf}y1kN-W0oh`pL#cHnCw`0-z zPD{e}6|jlr&Az{L-M>hNUE0^60f4Rj_YW!uiW8K&m59C;1N-{3Ine%AFHk=#)GRQC w6wXLYxC&fp032Vq+J8j4iG#*&!kUii^_i&=hv@Y_Jkmi703C{k(f|Me diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410194 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410194 deleted file mode 100644 index 3c3da42cdbad01c35ded372655189f13a703056b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6092 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 p57=U~Wtmu$L$ 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 ZrqMy-Hk33|KIlOz3eBqgF{!c&*V7Bv5jpnpiH` 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 J)HN{A0RWfCZ?XUY diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410200 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410200 deleted file mode 100644 index 336b92a9f09d896655f160ee3817e49c934a69a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6368 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 C`QUQ^ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410201 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410201 deleted file mode 100644 index f1aba9d150fa5471099a95a73b784417402a7f64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4928 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 ocEBkt4npxe5#~4B+zlede0ci@Wdwg3PC diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410204 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410204 deleted file mode 100644 index ab8afac47c7c054944d0e0e87476ea1533ab23f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3992 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410206 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410206 deleted file mode 100644 index cd1d9c6e8b2e8843de4af72d922d8ab60559cbf6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4884 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 E0EyglGynhq diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410208 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410208 deleted file mode 100644 index cf0ee7f8acfd158854afbad539346e177386db76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4992 zcmZQzfPjz3cHBt*bWQR0Gy%O&kvw+}99XkV{rHY~zZpgBj$OLC9H>e-uIu+ojXj(1 zWrc2B5uy6>t^eA#$G%7YY(KWM)}q_rc3J82me;8o&1|_{r~b^kGxv-2;?;_ES*^B8 zb@S$2dUkRX$fl%4r=~${WMBl*TVn+_?XK1EyL!ONed)uk6HfAnH;1~*90{o2*Tizk zrW>flVW%vY`{GG#ddCw*cCHYJh>n``C6R5q>c6Ova$f!T??naX(}-i2|PJj^_1~dt?(`-kH_rMkGDbG#K1r( zu7K)TfS3uS-t6vEOP{-ymltd*IIVHum`usN-XA&ohs+#YCNqRxyz!2K-^l?O2J?VQ z!EpwqCDKgt3%bmTv1ImiBD*Xd(ZPC;*v~4-QVC6);KYgq@YAUOGTK@K5 zs=b!2%H?=rFTeXYj=wA?%twH`{Lx+pDN#)vGZie&A2PvK!d@4Oz{tV%2Xc5 zcdXh|X~(^*o+G}pnXs~UfNzRe-mJ<8O~Xk z%(%l|)ArcpXI4ws9G@ZZUzw-4aM{&5F zDzSK7o*`giyiRN8;%lFQ>LiM4Zo!l@g8c^!OGD`mLD9V8tQk_XpWhPs;dZ+ExqfHj z1sBPXS06(Ebl%jE~!UG0uYG z0xM%<6LV9b08|W46A^w)0ii(wKCWQBV1kHnVPN|8p#iFc5$aY4SH-z?xAs+btv%wq zOCW?Jxp?;ayrq9u_^N2AUYz!U=bA=x=KTuaySpnoCLG=MOt*Tso=?C_kyhzP99zHV zFi&Czngsy>e%-$UE3d=YeReSVZQ-&q)*H7FTNnRgfC6V$GSUt=gP#R3# zRy1h3c5g-drtRkThOc!`RchSdH%p3T_TKrzMxSGDM}ic|o=t^mVFa5Cj9aIRbG&&9 zb*HWnzp=2f?*r@V1&>oy&5yDz_-lE?Bw^mQHM}$L{%&2kquN@2{r!I3$#!d>X78{$ z#xDK->FrfZia})oi~Y&wo^_hff>pdidDir7d~dUGOYEfJ*Z3osiBW4e^H03`K z0NJp3Wdw46LFGXHVg{BK^PzkOBH~d@Vf}^4hyfr<~B;g3sinmBM!k~g4A9B8q2^io#ViJ zhRqp*tI}mE<)h4XnYGHVZZ>>3ZSM`mrDq&ZtN|+ml|K*wOFl3fBnk_2P<;jl1nWPb zDsY~I)PYc42nyM7s3=PK5odnN9B3VjFc@wah7i`YLj!v#@drk*APFEb;eG@82^qlh z@&b?`QaS+X1(jEza%KUL1_KiPj$uEN01^{sI;4Du^AP3C0+1Mr+emlQY-qe=*o!29 z#Du$o*ziIrkBMoELDM?C42RnYWMFX!N*W>3e2^Yu&1bN-KN7GY{#g7Xo7(;B<03x9 zH#3^Fbn9^)iw;jWudloSbsx5R=^s=MmgnJi648cXU|)Z-1=^084m5`qY8IG63I`-6 zTm`PU0o#wOULw*>3N&^T$nCK3S^)FWAaNT?S|ia-ptdMA;t(7rNO>L{M2l`Po4xp( zu)0!3D9%0ql{6E_?iOap>g5X=nEqyMD${|6BYM3A6$VqVFo&m6g6&BL263&GO|W_c zBOM|MATi-ql9fh@bdv>@%QW> diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410209 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410209 deleted file mode 100644 index 57eaacdd4c78bf1c68ef5120bbebc6d10b1d7621..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5012 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 TbQ5U&ff{iL4ioe=3JWIy?z*6E diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410211 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410211 deleted file mode 100644 index 622e4eacc073d5a0f97e702bd5ce4d347752bf26..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11720 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 ArT_o{ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410213 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410213 deleted file mode 100644 index 0339effab32dad40113e28dab617ebad5c7946cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6184 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 AF8}}l diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410215 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410215 deleted file mode 100644 index 3db4b13f69ab8ee575f74e961bb887aba6e4a61f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6116 zcmZQzfPj-+VqzEOb>t==o4Ik)%!P&*J*^(>*f&pw%R>3-mFMQ4fU1O@7HXv*QxW<0 zaN*L5>ERo5o-;U`*F+l4!iRG|3+?i_RZ7vZ>$XYW~tBMKS#Rb>1M_W)$6{#VxH+ScX0-5tybxV{H42> z1}-ZJ;*I~w&#YdvIe`XMESa|xp*z3eW|Db$kA{g(@6S&RDgXYa2E{aR$)28* z*rMz(`&#kM4E}PLhu2e|ty1b*IQ30aiIGU)$;qmxjIU~icPV*1W{-Zn4dNyS210QK zRL2U$Od$1L(_V*|Pn>+$d4+I7$b{RT!dyyAk{8Vp%yGK`Nyn*zA05CqU0x6IfM?rCcm7$4&DU=VSAZlOQUM_zVV5=FrIa0a646E@wz-iz`}T) z*38A%K7*7=6i78dl`}%z$>8AdxQgA$Fv;cUw@JMs6S*twE=c~K+*$Q>2dmun>9+lq z(veBmcSK)SSN~XCw9R_!fsKY~JFMy>ZXbv~HT~g%P9C6n;4n%4dgjN`&eFevEnaCe z_RL#loEqQD_`9X@{Nm#&XKU>)Fz`D$FmNk^?4Jz8C}9HR!vIJeEGJNVFG8bOwe^B%_YRlZv&dNplbMj|x%sTF%@FG1*Xlc8j z;7i_RIiF0wG$>3eo&8#4Q>RC=+xGZQ_t?A9VM%Z1IGHd)-QdtQRU|<6-z+B8Y{q*# z{~y->U0l@{Q0%(ppu`uq>SHl$lynYE=GoNJwW(^Zj`7beaa$j+VSn7xw*A<5&UhPM zKVG22z~NV4|9i)JQ9*W_5WbtLcQy;OYO-uhD}S54Ay_xUUH@A-IQ&FgmI2ixhaEDT zK|#{|+wFAC&1rr|u3AXTyC|`jW%IdnZB_cdG4yNhw0odHkUg6UqCkKVY%VY?{%)&% zTYtpmYS+Cr9zXeR2G5xh{Bak{ZlNoIx9qi(r#(~;n(=gI?KhQ6@7-NqT>R)Br8wbn zj9mOr@%Ao>ge-fw9}HhRGSAqccxD=lYW6FYZz-JI&Pts=N_n1nCr_GA5HE?KsHE>6O=EEjg3uAAd)b3U^>M=@F`Py9N)2OPo*9Au6m}- z4>)|^&mzQXpTv~U`{f#MY$x2-3G;yV``oDA7{TU=f~>Z!ud2P_l()o#rG67}h!q3V5T-dGJ(Pu09p z%BsiP_xAR(eG(^4=PCUD@~?ZEgBR1u_fZ;}TPJVa49XNJc?0YgV0yUmF8fSY{prJw zXRh72DJ=FqYQx5F+69aEMds_N~T%o`<&6(9IKnNCc58X>cO{;8YG zjcz8Fx4k>><{xFPQWaVtBB*wJTCh6{(0!~Y7e&b3($<(D{#zkY`|jn7jlWY$nALmR zqTcXD9Jr%&2dD-Fz%>n!hNTs-Ad~>b0W*VW?lqVo!T10wv}WJX1uU;XaWV;}4@M(d zg2aT$LgF0G1KAA%Q2Ub>1;O0G2&yMx>WFlc8jalqOS8c68gy=>B)mZR3I!lV91;_* z1e|Z-Ja`;J!UU~N28v%$c!A1hFd$fWt-Jlean3JMpyCa{Bs&4B4NhTk5Q^W4F#p6) zH6c>W2c}O%d=p)6AnAcS9>~Dreg@aCGk>;cp5oYcn0I2Yq>;$B-4C+mZYeE&_qOBS z=bQeSQ2oT@;b#BC^P znM60yBOk-dWE$i%6u%Q;{>BaKwaCuLM7NER(l0D;foN>`I8o~H(Q}KA>Bye4T)(E- z|I3y~j)liw*l${4#j3RJ=(k5u{VD%}0LchOAomwk4wN=g%1griDF$&F-*gpdpQ;zA zAJp%F10;7MG2zm<%5rdd4J^yILsg>04RLNtJ3wPMVa>;b#BG#>7pPxMjW`77RiyeD z9F^4}dw+@FO6bdEuiIYgv*z0JCd=8;|K`<9czUexa}xcI zVLy@p5|a$KA(gkpxJhee6D-~_>_rklVv_78l=dId;|NIpfZGUUU~>qg)Q+&(yB=Kn z^83!F>9fy^E%e;J)#s2A^Q~F2{l3XNtD*X_)f@kya-g_JsW*riZ(v|wf9wQw%wZl- zKP%KMFoon!Bqm%1uC#`?-XPLVuyGJtxe06DA0%!=DKAKL6KLFs8gYnTUce(A!~g(Q Cx}jzO diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410216 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410216 deleted file mode 100644 index e699e0ff178dc0172181ab326db2972a97af16a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6016 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 K8?iYONfH21GI31+ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410217 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410217 deleted file mode 100644 index a0e424ac4da1a452667dd2405b8e009489105094..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3984 zcmZQzfPlbxj!XXB_o`h}5YlmT%bcrk=5lY(DdK;zYRTirYXkDCfU1P68M~Q`S2?`A zl2GapULX2VId$3xr@85ekFX`=UKiaxX9Dy8E&jRp0i{w;q|(SmNv7~ z(k?Gt|9}%@Q_`YS$00T{FoNi-MVU8~0=|3Zvd@0>!c@rY{r?x2=jgHRU%k;uUi?qG z3{Z(f)(wwCfo^>QA0BG`RGj87yLDz%mX_YnL)k7DPTBrX=I^PJ+cHbL%jtu+OXdAJ z<@P(w7G>MxzIwTa3VU75{3h4us!t=g8zkRddThd@HUHg$W4|$owyflRux<156p)LVkDrg) zKL^BufKwpR6b2t}2N3=K>}G4nb{WU6)tAF&Zeve6bEhgHe($kG2c`uy&8l2tFr8;M z|HG}_^6Cpsey-C$mGEp!S^LUATgv~Rv(TMia5Kp~yhp=Cr}yV4hLnGQQ-fj}xMWYy zNo-Men0>AIW(I$`%fsub&sHgQEu8wMsl-Sm@Z@CGQ^r@d!n>3_9B9Ai zo2AcItooxE}L3nV{+)k7Twa}StX&M4a;q_!o7Gv$|ZZCT00 ztIIrMPk;0Kzh%X$cuS3n7?2{_v#C(642)oNfqoEfE;3%HUZvsC{D0a;lc%go?^R;^ zLU&0tHu5u6$UJd)>0I|qVfF3HKe8(J@Hf7@BFL~|JKqJH4@WbOc7J)U266+~O@^-> znP+TJJTr|&HT#vyw-iopXQfUbr998PlP66l2pa;`r7#GHon~OrSO{dJxIJmn>32{u z&Vu3sD`OzA1PVaK;B<M7IyJ?Tk+t$^twrfi0$b+{gwUJ#ANAt-5tNb^B@h&7*q z+q+=d#K;M+I1c!{@-RPEA0*J*xc71KO|zn{#XRfyRiW-f&-2L6hUFEwodoL#1_p7h zl})fbiQ#P|0VF2eN?hp$Y(Fq9AB3tz2|FU)WI^Thg6<}e+hO4a&tHSYZIpx;dYmAq zWm4i0942Vx5vXm2QXY{QUbJ%?Qh7v-n|SWX!qOM5+ypPvL3x1aHWrdUK>A<+Tf|wv z?fd!i)ZRUvuNPEZ`y#-_m3%Ayg(2gYwhvCnwWL#TL-nTo2Ld1)W&|UU`wuDyOaJil zf{3;l1N-`84AA!20-!mdwkRCHECC82G2znaVGT-8pm0LZn<(j@I5!=gLt{6A+ztyb ZczH2M+(t=wEd=_D8gYnTUVvg24ghU=mQerz diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410218 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410218 deleted file mode 100644 index 9ace28860431465090334bf3ee74f58bdb37ebc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4336 zcmZQzfB@l=&L#i3Ik&Bs zkjwVmm^>9^Q_`YSXCO8*FoNi-MVU8~0=|3Zvd@0>!c@rY{r?x2=jgHRU%k;uUi?qG z3{Z)K-de+XZsI4@I`^8Z%`iW|C2yaL_NhOSUz_;uPktKq?owCXnng*T>=u*m|LXhq z^7Y)-37J{O`-+{9O5J%A8@Ggs*Ej57*KxDdUtHPWHT9kgU+E3&x^Kj15;s#=O~OyM z;?to6M{AgV{Ac?(b=K*)HX)|(Z!av++UyzZvG}m%xyTO;qAjaJ!O1VE4)j|<1u^m<82T(F)$E{ zE1)`NAZ7xoZ>p`Y>5)`hGDlLG^{;%cDM z$v_N_Hz17;K;mFIf!d4NIu^zrO?r)T-&dU%xj3UMpCP0u4o3ZNZW3yX&alobX+miQW@`_ZfGwZP8>2002M*P1ExUPXt>N;< z-M3RiuQ5X1;9wck+I~>w@*mCwTc)&glT5<4ez|M-+S4xmriU1lQ-BCpY-0QoZ8^(7 zixPXQBbS}relUFQtO}P^@=Lk4tYqTVWgfAozxn;&vSL-drA7r(T11!+wig&yMjwrA6|(}{Cwh?L2a*Z_c+r zy{p+_etdFOz~WYz^W<{^QDtVIjf5hn{qd?cc&zK`{YS5C!Q5VG8fgTor)nDEN&S*^ zQt0>V4GX8=k;$L+(AqCVhtV)=$61Zou#43N>w)&6q!F-Nfc{Q?E4jHPBBgDU@+wZ1 z?UCoJZ|an)$xhWZpT!-fzs}yxcmB&KZam#T-x(Y||CJ*l#q~PVo|SJunVe|f-*MyM zWIk9Ld3^1OU|~U_9^b=~K_oRYTx?DWjjbD5Jm zgS>PX@~yn1xxnX}`8jnNZ-x?9p!=AANo@Z0^Zpt8SKD8#t}xoxZ?iIpe}_@+v+ON9 z-aYQft^%rI0EZu#0gpon4?=>{88d@u?nRg&!T10wwA$$81`>_-wnVv^xD(%rNl8t)kP zA_*WdNp=$`oL0hg5z~%=rggX;m|hT##UUtZgh=y2dWbcj!DRaup4WGO74f-xp(hq>?W*b%OG(ZCE-Pnx*J{|(V%Wc@jDUbH_IQ4BD?M;x?hM~-oY{# Kkj7F@z-0lx(Grya diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410219 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410219 deleted file mode 100644 index 19b9595b10257c2e37cfcb635b88026e7239a66a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2920 zcmZQzfPi@$tU3Hof9caa;5M=H_U<`$>h>uHLe;e~4-Q4Vn{QhRR3$82(z)b6H|Mrh zwJN8blqc=h+q!TEt2EPJH~SvjxrPsfuauQYtd-ttdUsVy^Ze@6-Hb1%uQ;`{a=YC& zqqVPlW?u%`l(gv7MTm_Ij39bztiYz-wHkg`4_LV`eYkbPN&fKWPX$gwYO|5ZL+Sa`dNS^kf8ZpNALf{>YaBxWa9Yw63D zUQ=K1m$KC5vf$mAOYJN>Y*`cjWS7csI#_9Na_g7>G2t_&+(lry$@x$|A(}z7Wi{`EZJU>;fLzRc{QPpR zJ0KPWoC1laF!*>ofav#UH(NWl%Q$wez8p4l8++23J5>qsdyg$TFfE{IR^<|d={&Rf zA8zfIS6^uIbDjRFglAjI+E@PBQvUy(h3@=}$n0Gx*D09$rs)|;oPI|pf7U~5zYrZp!>k==HDbdqRu`;i;CFHWhQTVJdT^Wp zX%IkWGu$$J+#PDXcEZGCitDq_rs>}NGdn3@x9Lr>)^kn%zbx878f4F=f+!GR1e*(t z+uR+Nr}xZUw(8!Ew5y9hTtB?QQKhqZ$!=FBF1!5nlJXnZH=WxQaLW32-fF8O&-GP8 z=JhD~?%grVba`JI&(V9I*??w&{K4@3-pps`-_)kaI4zR-q;ccYn)N!__F+9m0Y>W4 z9Y*VBf&IX(*a%cQ8HiEb4$=<=AaSsqK<&kB9SdWRCcQ?v@2k#>T%6IB&k#}+a@kHU zw=L|!9GHfjS{C6Y(?k1mtO}#0yUmWtI86Gq)04||>X(uY3Nu^yf$GFP%3i>fGlAU# z^tbf44z^|1Q(RvB{&dkumcQVh?9tZ0ou+XM$}dh|B#||v<6+Z9*>5&w+N$r(mqg5! zD9xGT%uh(xRY)P&r0W-i5M>bJG>&RWx=JEZ+gcYtXrklJElM zD-?hfaY#(K5^%nS^Wbp^2@|w>0u;ZX@B)=VU_dZ`uDjhVe=tfEsCWY~OHY7mgHu=> zgyMH1%+J2=RYZ#U!1RfTZ=%Z$Bt3A)0~uJ{&mfr0SAFwid}VXWwUyCTm7!%`u}+E) zjb}ZmF7f(eJ68>?pQwC{2xo$I1FU>QiW>s%L06Fdnn2$Ao(ZC)`{DBdD zNCHSqxKGK+EAVoUM89L$k0gM^B*Se;X_*)|Y0Ywg#XE+*NCHSqlHG)oCy8#uAo&As LBang3AuxFWuc_>B diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410220 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410220 deleted file mode 100644 index 1d2bdc322dcc7cbc66ba61ea06b83efa983a1056..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2900 zcmZQzfPkW!XIGRXymkcHKWRFuWqLyR=K2Z$U+NzH;OcBt^6gR%P?hk!4b~j~r@!=R z9&npjd3*O9J9YaM1EK2Lm-e^pi)bK1{O$DIDGdBZO=b#lNFw<@+* z4x8K;r%nUel(gv7HHeK2j39bztiYz-wHkg`4_LV`eYkbPN&fKWPd^#Es=H z1$wHLt19J=H7sY+s{XX`K`KLa$O7}FG3ok?C6}z-WcEPUdQB4By|*d`dWGK~h~1lY z?Rik=Rp-YOUL>Sz>2#cF6U{%=6foPk`h7%Uz2HZ8ej5hSmNmQ&wryUX0&+3)@$*Of zV?ZnjI0X_-Ves*G0MYNyZnk!8mvQV`eK~CAHuj`5cd8QN_a0kxU|K-atjZ+@(|Km| zKit|aufEXa=Q{mU3D35awXgiMrTqUn3*GqzH_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgJZfX2_{!5neJqv@gf1Fj~6X?3j$hq)$6NxlE^iDcPVfvxT35-^l?O2CISU!Epwp zK>(S}P;y+%YjJ7C3iITnYL`XX`b2wH?B{ta?Y;JX$}8txk%k}*vS(946bLYa%>~Bo zPmVMCx0XFOdEO__n3Y%q+HqDRHtb?` z!Fs44R>9PR^Z)^hAL4H9Pg&eGm8a(QosQKWEw`5i&snh1S-HnpnU�T3i4~1F|2$ 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410224 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410224 deleted file mode 100644 index 72fd61b53c6fd43ec19896a51de4066567bd089e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6136 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410226 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410226 deleted file mode 100644 index b9d6071107a8c88b6d2ee8f322e292fbf45128dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5920 zcmd5=3pA8zAAiS?r5KfnNThFLrDQ~C7nL=JNfMn+#h8dyTd^+nkxEV2-PV%pl-!nf zq>NjfsN9X@ERxPwZXrxkES44D`@H6T_jNl)t#kG{XXg38&-=gp{*6Fv@M{ajX>s4qdl=7;eVdU=PJg>5;6TY$E$6Woo6I7EeF-*4Y;UgA5GF@=J3ic< z?BIN%wwZE3;u+T!S{2BVXvxV;VF1L$@|qrMDxf9@7pyWM3#t*A`>HbyjF}3?!R$KQ z=p0e{;}>Tfjuez7JdCiq5aXM)C30CTsWm%9>GOErlm z({=5B*htp+aikw&jDI+4Z66@6SjBP-TyGTH;PLzz$$MApv!k8AsRYMgdvn2atMuN= zunk=8r|NdWDrT=l55CHo!~{X}fkUyElCw>_#u46&sIWXu6k3o*Wn%GH?llt1)WWBB6#ov4gKV#3{ z4k7Qul4WNpD)*Y6QW$Yo#mzK58~wu7;RA&iEn$8ktNqqi7P}Ey2jRt52W-EqoRK4ZML`4mmuP68G zw&d2mZyh*$TG6?2LVWqi^(!PE?M$Nvrc3iN5kDSH5Wemmb>45RcBt8j`8yHreWkXeEUZ&MIjuZOs=cQ9*JF*aP9b9(3e6fO&>=`H z30j*_b^<>qMyKv>x9MPZ?DZe28&T^G8DM#wN=z(uNUb1*$NjWQDbR21(&K>M|N428 zMTT~j#5HjgA7$VVR@L30ry!7Jmcet(#Tw@t;@c+%H04`}x-- z|1+vMBta!q5LV}I|S`}MpgHI*I!T(KII zH!=u_Uf74UqXFiBji;K&%XPkVrLT=%)pGaFr88?9n`9|b{dWf1nI_e1g{ohK#Af!^ zo^_-*TfQNNRRoqC>1#0~_luv+t6s>hk29*W#EI_8zh#>lD?v)^~g6fAZQgnXqq2>)& zwls?`*NKd_V~2+gc6Jeib{4+ePlt^8_!txLz(FLykE8r|Xs>|185#4Q?+_%jG13Rd zh@A0YGn3$pA`>nSI1=NSD>sOJxR%jYFxO`nyLEdSuPa=7NRQ)@_vC7`uTx8kEqb|{elB4JgNr#< zqx0T3U?Jq3oxF44bs_XDg*hdDg6U^~{RzW_H!_RV2i;TCWtmhn&O$p!j8!#-{SM}7o0TrCTNN&VIZbT6J^7q@^T z7mR62PYV1y59bGF5hi8>(p&n=2c;~|l}lxV63-5a9p0Nsf66F!eWA;v@xm%n;QIqI zX1mLc^WTBogFP0je*yl(f<*6>)bszxN`&RX?_q445k@huC<{ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410227 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410227 deleted file mode 100644 index 8a5b0da8c9b76b221c9811060e3d2546327dcda8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6140 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410229 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410229 deleted file mode 100644 index a46124cc12bf45b481a7e657105b98c3c00a5b74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4728 zcmZQzfPl<^RcBmo{c+2%bB&mC*M3!VS3g(Q%7158^j@F5;_jIupekX}sPtPWf40>7 zy^ybCb5myjc6F9>#XCi&5B0fx>ca|xp*z3eW|Db$kA{g(@6S&RDgXYa2E{aR$)28* z*rMz(`&#kM4E}PLhu2e|ty1b*IQ30aiIGU)$;qmxjIU~icPV*1W{-Zn4dNyS27+5mn_WhB<|q&aOt8l|JU#g~=Hi`GK~!XzCbhWBhW%)~#;YTK39fBWv*_^`+-; z%uoFE)_>2H*Y`A)UV+qycpCyKBHRLWa|rhnuv#F&2zDPZjp%xOO>$`5YwNMM(&?^q z?y?OFR2Y-rKYelf&v&<#O!?o~)^9oc<+6(U?xq*7t-`f^k1qPxIs00OU*Dal4(?NL z^8w8QhlSy5N9GwD6wgd!QO$m(@-2mv+gYj8M=8%U@8n6-3Bn*prZ5PIon~OrSPrru zh~Xe<(HR{e2PDQ>P+VYTY;0m?36X`V1Jfz~flryrB1kSiVEMUp_SCZf@gmsgn5rht419d#uqRD#3SZa*W%>su@*R*fSC|nFp3{0VX zkP@)km$sM7-vrodhI7^>Gw!h0v^_TYnbp!Y$7cvUIe&jy#too4CdUxp$RLmoC?FJD8&vm4;&`1BR*!GU(j94zk6vO>%>JW1%{vg zTCc0|S9&9KTjQ}u9yH%C(v7{8hSwryjcR{0NFymVXutw|tYj^vL0{gL|Za zz!{rnoA4U(r7VWq8Lghk^O`^{1($k2HY`qIG)Nj04$RQ90mLU=tOu+S zN+25!7Xp^QFf|0rDxgB3`7$J!5Ap-dAGEZG5$Gmz&Bq89BmpEQER-PW6V3z05ePu- zN2`Nje%}IA0XB=um#7pnVWG(ZXIxJ%Qa`2JutBv;EYXy}ho5 z++Vy#*k9Ct_ry61_sH8;E!E}n_&pEmzLft!faGRIAom|s4msSwLPXRZ4D9O?V-gVc`YO1B1kEl!O~@KmrOV0#2h z8vO;8gM~S`?F|wmT#qw|%lM|nKI*jg|ToNCZ72cnGck4w+)sz>4Ulsf1-CO(| z-+t7C#y5H!0-j)i3|Jc72oogOu3}&i*IL;$2UvH2+Ey6p5J>=u2{RpM-3YcnY0;_o zP?acQPNbVGXzV7eX>^ddjgs&}FE@}Qm6SL{Pop5cpn4M2Mg_}(;+DklqMh4FbQ8}V dSy=j_m7CygL{K;p-8Vt<2S^_bV2e1I90271gLnV{ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410230 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410230 deleted file mode 100644 index 4a9b313035e3a49eac9079881c1fedeac6128241..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4808 zcmZQzfPl#F*VU5}q~3G=>1DZfm(lXVSzYm4zv8*vY%}_k0^XhjsuIo&Sartb)*rVF zJJ*OQckNd-clC2+t^9XpMep^=EAE~tdi7oT$n+zj-g*SY=0W0^V54TP@$sgVv>MnC6pn6{u%O#s` zpc02fhVCL}Inyl`$0~xkoJD;EByQbV``0QK4t>8A_?G+57E!%h>Y}>p%1>|DpBbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}*}54TrNX%BV_yHXNnvv>Bc_Ts~ahZy*s9Drf45vCrb z2MECN2VpWWSk}zYOTRRE;j&z%NqJAS^f@KVnWyi4l(+lXw2lZ7_EL~K*|VuI<&0o+ zfpNRK_p0K@*#X9$-*weDi>`fc8k~G7%%iY=X%`bw+LsSsNSdUa$?g-i&J7u z?!7BgN>iCaLtek#;PKzIga>FK*bnalm#n_RxJ755xnAX(9>vD_^`_UJZU1MnG2MjY zx!#3ls2{ch)g!wbnawbAx!XUB_DwDQ_xEQao1NA_iQ8s3 zN%EpOf;moCA1rC}Im*DGF2Eq{m%+doHW6e$$Pq9A%vZ`lHb{)4pt!)w(8RzL$_FU{ zt9@yEx%^Flt!6l9T{7bidrjM8lb=~FU2}Yfz?1X$mu1`ls$+5t@r?`u>41XtQ`eF! zX7QEwZvB<7H#v&K?No`y>+%c%3*&WKGZ$a`3{oahAk_d>&IoZQgM&eT`bEFX6ZP2q zqi61&bT_T#kd5b?EsTGbPTbd&dtu7^44LD)t^HbW%g*R&KehdH@ZKsOW4*Nd;mbaE zdFfeAhR3VnYe(i88x+q>V^Ph1rSdI>liOLT(?==KGw`vTQ71%w6#__%`gf(c^6g()ctrhyUaR)_N1T@N(gC_8?5-;>wUt`PTrMQwYc z$0Ju8%g?a~3|4k=&%HBWMU_R*O^ty)HuSgaHN);di&rXc-%}-cQ83^c8_+JxCx&NSYp!CKJ%+sL! z00u;aGXwkj!!FRUUJlg63e^gxV3q(mNKCj2aQcSxKz4%w)P7*vg_*?&Dr;fth;!4S z2Q+pQ$nCK38f|{bU?qZ&_cFZvp=T1- z7`V;m=aZ}(`Cp%LiL+^D$;!9oXeQi)nu9Hk{({QE!W^DP373xy;xfLeKcHpg1fV&f zas&>LJcY!BOOusGiFDHx8oLQ=8XY8VLrJ3~x(QUzQ6mnqrqSLMmHgSawSUiho}@l! zPiV{C1*Z)&!(y&J{80Jr+VgD@(3Amg^#R$q(hR5^-2_WT1lv*!4B}cVo8|!ZY{X_J zk|jt?nCUq4AlUw-MW?<(RicDBk#4e}v74}_(Lv%iO2P}h+(1q!q{Jb58U^VE)svv~ z1+RBV3@_TbjYK!`+>wQ)FIu??)SiHc6Vd$?V{vNp$}j$sceVfedU8fyn~^u%%Vx diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410231 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410231 deleted file mode 100644 index ea5db50f215e33d5ecb6bdad13cb505218a1b1ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4876 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

n) z1u+QfXJB9hsSois0x4&h*xP6C+B%UnqI27&)$>`Nox8ODncI!ztbDn!GPakkjC3pZzP->&^4=QQ(!iH8!BXNm|H z1}V-wDSz&FzgoY+qfJj7RUd_ah?|@DyI<}G7tkzlIu?5gcR@yK%Y^2OXa9Mk&$i|zW|+Wk7`2J>0*-z?fESPvS>bDVp6 z2&e`K7kA2s-kSZ=%$;-{C{=WX#`U&j3Gb8?flU{H`;vJ}+0s=4^mS#ZZ5DdV= z9G*srD90G2E*0;9mW3ewFmu6XB5{zIFzX;?51dD28YR+AAvAUq)-*au+=h}yNpusa zOhbt)Bn}c29&4a*Kn9R95n84orBRSxWI3=|M7RxJFAz~j!rTF?E0Ns`DtqB&2@&>! z(lsm%(Jo9Va}!F~BY75y2@4XOc@3j1aTl$baCRE|x1GV)IS%#S(b%Tau=vKLXFsZL zT))+J{tc+E1_AVP1ldlIyFlR$YA=8R5p_BP)2|N=$a-LUK{T@AP;rzrPNexVB$$si zf78GoO8kKlEJy-KOn6A5q!*wla(+bbo5SL82Q2uh+=hcVYU83kdPl)bWcR|t1T02n zdm(K{?DjHnZaTQ0U%4ir@%x>n%s+Y3e;IF=*dljE?eH}}&SLJQWQd~~QlRZWn41}q z+JDI523Af)AB%x~{UHfxKWi0G6D!mnFa@&&$U$PlRp5$KP`rWSR1B&T7N%e>ac(-e hg~o0Ixg8c>@UnT3xQ&wV0`--t5r-IMGc+#26aZ4)>!|<$ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410234 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410234 deleted file mode 100644 index f72536d0d6d2a3a5ad34db123fc395c917ee2a4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5436 zcmZQzfPj>3*I(?or5KyW5v%mEd3)IHKV`T1Klti)-G9`pcVY2cpeo^-1+_b5ySHc< zR10vV9ox@(h#}zO7m54Z%Vei+RBGL;w*1KR-0yq(tj`_$y2$Lyv=_V?b<&yF-5-ed zUdX<5kevf$Q_`Z-3LqK?7(v9=Sb3?9`f%%nll`ZknvGIVThBGT z5_3Z?a{bE9|2Chk{Gs*tuI5EvW`^wQlQO|;+BfW1;pW=Od3tBTqO(D(+^RJK&xPGl zP;q;&v_wFeXwow@)VGZnU9}; z6}bb%f`C&X(G&(BZwCrW^Q9oI&-HgA%5?%MF*w@G|j49VlbU& zHvhw|-SX-SO@6M^Kb7!oOIiEMKU>QGpR>@NUvM+YJiJH4M5p)XCx(=Ne^Y~E8n|Rn z&q-`ic9?yw_+|!wxy!@rsn1p^buFCwrm4h8B=F>9)lr5*RKdZx?| zIDFsFBE)K+#FWqbntg%lnF2zC0(@M-dcj2cscXp zh4DJAnTxM|1}S28w>|(?473mGR)+-T;OP_hMu&aNRTlUy|GlDP*Pa}v8E4tz9&b_> z{bwEGB{xI6ig}oJ)xO>$vtS|*1HY341Gi!$Q2k^eMhO=n9|l0;U^#)>i`hCB z#vV<2jdI^tofo+{qbr{wq$uRFom_5P*n>GR4d3Sfkw0x_yWO4nf8nXzj%AD-dTQPqi`8li+AT$jl9QG z&TtuT(>f~mX_Mu~lXiEL^FBuBhNm6dHs^tgp6-h$3|g}{I_>$y4RwPCz`jn^=BLE%R_6uzi6!0u3#@J z^05fd*5Cs=3><#7F@CvW>sGgHEqi6Lk+pb|`qJ|^<|lr7>%Zs9>wB6?ufX9a+Oi3# zo*CvDAPo;Mg8CU4*g)z-yp6!xt=&J1&JDHMtX9;m)cVN4c{|IW=QFH(*gt$cX1;X7 z8cU!ej3{K6AawH9d-r^XpBo zJ=^}zVq>}q$8)_4%~1bt1**sDUxNDK{sm=81_mvKIgj7`RS_{;6Jgz@Tk$pIh2p`+ zBYTS~C$~@YHhomS@ioV#A3PmIGp?C^s?+l!}?*Ibx>X5mkj&Bm4~ zO!{)+HdDBROXhB!68Tg*bA6j!-7_QAgQ^dn&YmE6|B@&d&|H?F%MXj&xkT`JxI z)B_4bkbaoCU?Y$?NKBaNkT`<#U~vGoA6PF5K;;-gjV1g&iW$zzbX1e--fTms7yqVpEaQLsFQ>|Rj1CO4jF7bcXs z36%ce0LimROt>_PTA(O$Tp+gr8Tc5LRdQ9b|DALTzHpoIj@TNB?>ApAyt}K7RrI56 zNS+4NMD%h5ZV`|H%@?_sVS)tfZJ+VS~eJ~oyLr6@REUq*Nu|H{1&@re= zlzc&?oBC+%CQw*G!wZo<2Z`G#2`^Cl3k4uW91;_*gxK^6(hEwvp!~cMrkh|pZr!c# zIp1H20@ZH-7H<<^`d~B`2ch_#2=gDPG%}H5J_B-jM0EQSsl0%>9YkYsKf|$08;gt1 zH8gG4_IZ>2{u6U|qk$KT$+O?BA+I;yliqy`sz2pF5Fi=B2;}~Q%E8j*PAH$4ehCBn z`h#1beUsHdeXKCOAR5V?NKCj2TxkGoKd>&5hN?t~8zTBjAU6fj*i9g}!@>(*&kPc` zQ4(ID{v|cy5WPJBj>?mg{8sC}rff{M-V?dU`ScS;Mb{vov?J|XH#~T@sxmSS8sF%3 z4YoGx7N}YVBKjz>HY=!~1Bx@0w1~t(V!}+vRoAqD?FXh&m_n2=C(=!zHY+XNgf)#0 z61PzjUbJhUp|+F2>4AvwBBlQeOD_c5tVGxgO4qP7M7uCSs)NXI6DSSB0a6A-V#1|S M)B;6uwpn310JgjT%>V!Z diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410235 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410235 deleted file mode 100644 index 33a57241a9793962ca7efccf50622e371abd054f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5156 zcmd5=2~ura%)S5byZ`0){kQwwK@i?3ociLe+S#Cw z9aD0Ks4Jqw+NECkC=ArgGq()&?`qq-3vi8Rs{_3=4f3Z*6ShuLqB6Kn4X{w-P+C0sU zTG(MG`Y?M-+GVyVM~oTAvFo|2uDbck%!4moY}eUwPmr{#Wge9c7~Z{hDVn?H;>J9P23u3xS!Wm-Ay>|h{bsgb8v zcPhy?|F>%9l4*$2ov1Sg{hf^XEit; z&6D)1xfkr=UR04%5=-CB4mzP1Hzq-$E%(5b>BkMn{n zG~dcfql4q;0Tu=_R=FBMbg}`B#tq8B;gwQj4Q_Bv+Hb3$v4Mesp&oqji4Wyx*skmn z30y5-@du4u@Zc7WkwpKe#fD;UTs-mci{enILxk>NN4Hvr%A%KbRgK=;*zy69x$igY z#;lTBUgb}D9OyHaVsK{W(bUElkV!;Yz650k_Aso};^eSk)8&O_!9I>})`l9J6b?!@ z1j~l_TXd&otWo;QWzoWj)05Q$YIAHd3|33OJvX20oaa*=|ejQ*74hu<%6`%&8zZIDl0Y@?%55Kg_AJVOGNFum?Hax;su$$Ee&wX}`|h058;b9TbX4z` zx;%O2T$&nEUYhhOebW1vLw@@VZGyXNH8!3IySTQKQF1&9@oaOhaTfnjnpvt{BncFv zd+^hV{?qOEq4Z=`$t4mm1GG)*HC)3(TNT}YiLdFmDQ5vbkiU+V2%>Qe&;r;&tuDrZ z;p@;hBnM00s+4w5!7f#GkKFNUV?*RwR#e5s6wO8YE!GitB8%=Vm;<HZUJi zD}BA$lPgxWew0m-ajm=Qlj*+TXo;-$k_#LOUCmf-x!FEfYjTtQ!Dk0_iaVcD_1i0M z!{Gv2c65?z$T>$I~~F5BYY^oGYywC>mGP?ps(9yU%%oWB`^^ zu#Si46dHrC$|Hyb^ohMCEL#NWAuSW%AARUU&K;H!cgM-sI~x-8O{6uIvK%ZM$^y9k zfJMcE)r0ba3kk&l@-K9pcwcDp$&AEVtRt6Vx5>_rF`a?vk@Oa|MunO+@272KI<{=f z?Mle5j0j+FF*<*1MUV#F>Yb*S9Vdp>@T7rdJ`7XG`f=zd8-%#Bo`8$BhV* zd=4~5{23kt%s!}xsn|0Td?(<1LiA67sibd|G2uA|{q?h9`yPK~13&+W7@|HQoIlX; z4WwQ%bs&w=VwO+beL;7&Wk~Lz>R$iVQe91Q(Z4D-NnbMz;{_C5ZB zy;>kvgb9Ju%2oV=)6Y;kn9(xsfZ!s7a}i<4|H z#^GmUxi6fJVeO+sh;J+vi}gX^oPd7sB?2J<{}Gx5fy9)5-d}jKyxs%;2dL`BI0f=w fNKE#ljOmO0;wQoOJ^q5<>^~xg!}|q4=#cmiV{D=7 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410236 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410236 deleted file mode 100644 index fd88249d7b337d3596e968320c699174dd905710..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5044 zcmZQzfB@m++vooba=M?w{qKskwc*USzm<+$W^vGa;FtM)=K24cKvlxK6+ZuvSzr0@ zvHZsW4(=1%A8~xm;Qw@iuc+|<+lGg24Z+Jlnj5vTeSc8ezWv@T$*bpji^R_d-{8G- zDE9jC>90dTHYF`Otqrk}fe}PsEy}!^6!6_Mmwoo57p6jH@BhEJJV%dh|LToS^5TEe zWq?W?797i&)GGVIlEeLU(v}H6j}|2==5iYT2rZa=xI<=I_-gft`gDQX;9WMCQvaLe zIXyKnd3ZHwgM8D9>$~%|{�PWmOS(rT?AJcCUcz1wj{B*3RWzvQl;Zp67FonV0u1 zzi7ARq5Hpv)AP6uldsg}-db~O)0C;ZQ*4hknD4QhF4*nOAlkBr_rbQ!%TquuWCBy~g!sM379E%t&@`)ZiNSQ9 z+58W;cFU_TH2Jws|5U=WEoJR1|7Wkjgu|%AG%VaWT`n46tiLnveH>bP{uRUi|79XH@{pl(OekTWD80-cr z1;-gk4-kOZU_L?p3=C`_wISYyAbkv43UeO6`KuygwkE>5OSj@{$P2}TjYswtRZec7 z=57A21E@sYqwED(Es$UYy8)OEX2^)FIK|em?WN_Zl%3`~xs1>KFcp5c`eMp?GyjVk z0e&ef@61(OQP$|SX`k<+L)Ock9@^hsyz)SKp)g_GM^snbU(&ol4jNz)0!AV;P!2#B3#V9;0xvLA@yAZgK=U?2x1##vBYU}X#h zmJnH(IxwB$ANZ81JdW>JwWrdKdsjVE<_8?U?`IKWwNGNo=Y7q-KrKuGp+NyYt`N;2 zGX2!GL%_m#oz~37*FJ+)&Y0E!rh#sNy49g~zxN)| z&L{6p|EW3KW$m6?QM@%dgzdd;+8%Ab3rQxYw5?n0`I~J!bW_%>^hgb~ z>(*pzo?ml*Cm+x}aJYP%|406`neBFW=KqDKayyoNPJe1)AoN-NIXA1;4ANQ9RKotGQnqNXWLg{$ya)BBK{=)IHa~f!+psm4~g3rSE|)(`q;%js6Wam z{1htn{`}NIi)?=E$m83 zn9bhVyV{En8y5V}3%uqLgC=@>_i#u>$Z?co|3Etw9C$R0pNuI8^e{bDx-S0e; z`Nf1PagYYtv#B5o1Q@~Q0{yU#_oKms{?%(1oZjME7@6|+UiO3eg1h97HkMuc)K!?X zUtfgPQU4QH==5XB2Uma1tKK72w0|<=>;CHGbFWJ3)Omnru^e0Ps#J7SqT;fX$M@$+ z7qzWL-}WsE$+OUVHapq0^xRsoji7W20Wf!i!yG6C%sQzun@s`hUGs< zTtkgPP%z67BEWD1mXR<%apnWvN4)tUKfwG!OM58s2S%_U2_P|Hp#({%a2_ljLc&LLdA^#|TS>myLUXN777Q%K=}#DuGW#}8Bl zQr1E0a!^}L4JwWjc0{_VgT`(Gxg8c>@N_>&+(t=wf!Y+*h(mCgAe9r~s4V#Ga&FD6 zyLUofh}=)IIZ=GGbiVH2u63IG(7+x_{DI+YBmpEQ+@~NvAp=-mMo$MIy~uK4 zvxx9JDeZHZJ7Dc}WcQ-fQ$*McOgr$nMK%X)2a*616J|XLbtqEZK!%%8>_*}sF-dk4 z1E>4dDSwVVTWGU*pGQYXq58C)((X(4J$djU<`_eEY%i=Whn`pA76BQsybAC45p4GY z+jcy6WG$d|F?yOp&P$~D4QxNKEaHMX4kcd@=O&peG>~sE*V>?>}#EJ=(X@ zYFUZg(kmdFk`|pdfY`{u2%=Z0oR!!!x0KCSb5?ZpnkCkUSLqvNT8P^A=+EAII`@My zP>F+@e1qkW#f)MP-hT*k6_20)YIWzv*LSpz9o*u+I%9$`gXmek)Lyx+2IvOQab{^r>K7u&0<=zs3gRRg_*Bvg~|gpPZQ_gJnLCCzPqh=+G5~Pq3l$ZC;)NaxwGq3mgw4 zKr9G21rkkR@bPv4(eKZ0wsvfnaqL=sIc(-O_M|g+suJS&9$R!^T0qmR$|VNVd1muJ z+}bU#zR=|7I{i}#&$g7cul%#6{Qo%%-T4JKlgz_=G)#1Qe|};}`S&+9D5il+_Vk>@ z7G;Oo*NSgu@Rz$hyq@}Ol~UKjsc)J}j6?!YPF6i-d{ryFOUdIgd-UUN5H|rMi$Gif z)iFUaL(!W$mWZ=&nM|fkzqZ0SF*aiR=9G8gwdZWg;sf-qKV8MZ@8kdsgWWLoKpF%< z@du7Wg8CU4*g$GSyp2Hm7$)}i*}Jw*WR2+Dc4_r|mS^WKt$*frBYErdw&QBs-q`H~ zDiQZ6djVDpBpAVN0Hy;SGscdNu8O4=cNAr(O59dnXw{Y%{owG0>z4Npp47==(*9IY z7dZgh^y>eV!S}JKz?RW7I)yh-ef1^6THPIPhi`H zlRRB-|K7UYy5D&w^NR^p;!ywY0oe^w4+U`l64Vd(uOV3L3r1Jg&WV%$ZoE-uy191w zx4O%-jjTD9MOTMuQEcKb|u4PL58!?SFl%*I%A}!e@l%pKN2@ zI^n|V)*IJLd%%W}SdI`;jsnY(RCwM;b|{FA#X~4*oGA16DII{7Eku|P3tyCULj!v# z@drk*APFEb;l3p{4S@6_rw_1MMED(;SBb6%VU8l0SBbC}RNlkl7Q^320!U1l^(2&E UNO_eEH=)>##6e<`>?XJd04GlWh5!Hn diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410238 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410238 deleted file mode 100644 index 93c5b7b42fe4fd34580b7b8a0883d2cc61ab6d95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5196 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 CdX4n} diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410242 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410242 deleted file mode 100644 index 340c16c7baa03be9be2cb5f14df96e86946a5d58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6556 zcmd5=3piC-8{X#}IiZm;xlDt^_`{&wa+eg7T%r#3Hzqj|WiYNMCJj2>h{7m3$|X&I z7ue0; zwXW0Eo$*8W`db4(t6eQusahc44ruyV%@JU+ZDE~ zsfT{nN2-;p(j*zF9{Wc0-}fV{b~01UbDhsEGjKZLwAz^Zn$3J;nW1g!ZY|MMmV5(R zVrE^p;aS8eu)hFCy%T>5OhyCF?WxFVNpxj<&rOAd%wICwfRsren* z8LXy5w2djnj>m7EFwM|bF>3!qDEyUghG+Keyaacan56izoQ?k9YoC+|JoMd#Yss8E zbvM1hv%(%9&yG`2eDwuKc3zd(Rch-#2RW5Q$%5Sn9$vWVf7^EVfCjzeh`Z|H8tYEg zP#FgGKacC0LzZlaulJP7(K<7B7L#IM{-~{_@U#a+OslDvHBf{jUaR#6y$5DzYXSRb zzZIG+-zT>`Cbz*QwS>;R@gRJ&+okHP$|H`^$HKCg9G%0N+g=>IU{R*taQ@=j&0R&I z`_7COvBqy2YNmgCmuay6psJom-0%y`@R6 zlwvZId!vJO<~dzUQmNIwqrN^yY1Je8SC2|~m@sTIUjaE9xTsLxV~x{eDr=K?^>;Q( z=UeXBc%(c2(&}KyFfNz1k|M`2c62i%HnGJ zL@Qw8Jq#P$R;cqtt9ln5EQq+Yh>~ujbq(guUK$=FV?Pu& zUvW7tw0A(#O2b%XTs$fcn`>!-i7m_p@=4(0;}YBxZGtO_h+94yhPtbwwW1UTbL!^Z zN{R8u7=eria|PeME^TRqf|B^zmqW2!x09T?sSgwb!uGIBWeirD$GRv9Uk@nre*)xW zR)uyG;#7nMytj*rv~N+|>kZ0LW0~18zZCqO+h6K181Q@x)zqb=s*Vv+$q9Ao6y`pS z*UJ5DomIK`o`>eW){5&~)ISMsSwA`p$6#SHtoiu9^t0DS{ceqVE%vISYLACq+5I)l zdRx_?uezOo;sncmJ*aYUuU~o3@SER7DWz^{BU|;@Eu|kX3~O952LMC-Da%-hG)0@s z*{v(G^OGp4zcwePZ|vUvJryfbY2AmzWe|T->@pw^;}5r>bSFM;lBc7mG*QjSy3u9`Xt5VApLoN zwZW;wc}7SG=%9B4{`hj#D|yImwL)6a9g(FfmYNj{(;rsmsi@zQ*uK!#&y3j@Z|T53 za9&qe?NCc=))OOMcrb6zL#?OsD-JGE?B!BIBbb@m#ht0g4_(N82kZb1gpO6r$JG>G4<^RDs z_q|I@Pnvsypvkx9@p%4CB=m@WdNIng&&*oeg|EZMxj>lwO8+;*m>^d;Uw_8v2ZHTg z_<}W*uT9T~JWfb43YUR72=3{Ngn>zGasIuw&!ebPK>i%aIfn^7q9 zO%}Yi3dge|dAbvIAK8m=b?|k`&t(^fJ~iad3QAmbs;)WR{YBrJvj6t9s3|?g?QI49 zw9Ww2!8k+b5%?;^-Y@69mq2G9Ouk&98N?4fYe9X&XJ`phERcr8>in``mZ;~*KGV;tds2h8r)nSKt^j(-9|F{w zsni!LL#z|SxLIXdzao^-1}Ow4{)3{2=ov5mX9SB~XX8I&Awb~$GvgoPQ>bm$&%gA1 z?uNOAjEUe0tt|*9kSC{luANHE5#PaJE`{Iq$PHqgDo*%*mw+DPNPrqXm3&HIBkxsW Sj_~!2*u}pU{+(UIKK6f0_IW7) diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410243 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410243 deleted file mode 100644 index d224ba2805e671e678a98469cbd21df0e5216615..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4884 zcmZQzfPe!V_zq3bofr0bf%*0fjnDe%$(a zzexI&m&^f;tt=Hw{0|;I$M&#omB5ywLz1<>3M{&+Ux)r&k<2t{KDVD*QO3o2*BNKr zTED!3?9`f%%nll_%z6-|H5=&X%e&Hxzs7H>YHmfw`Q@e^0~x8P8uDM%sHX z`<0&(D{r3=8L})p^u^yGPH{e=Zt2%+KQc%)oi-1UUpk#ZwB<1GgKe9ar+{3{eEfoh z#Rd=y0#0QB=@bSZZwCrW^Q9oI&-HgA%5?%MF*w@G|j49VlbU& zHvhw|-SX-SO@6M^Kb7!oOIiEMKU>QGpR>@NUvM+YJiJH4M5p)XCx(=Ne^Y~E8n|Rn z&q-`ic9?yw_+|!wxy!@rsn1p^buFCwrm4h8B=F>9)l;B*s}#TwrBvY+_*wk%g%P(<%OePnpW& z_>NV3D($#;)iY&&z~TFT79m#qB&K}c*X#?_!W0l16yW0u(F`KfPhCr{n8jDxyY*MT z-sC6_w^Jn+ugfz8ER5G_&0Ku#Ge`}ip)QC50Y<1>9cGIg{+ux-<=nx;w+h|Egr5Ja z7E+&8y-Tj=jBSMWjdWADeBbKFmnUs6dTPD5uOR)w&G&3?K09{bcG>9rv*NTaC(tZ# zxDa$RW7`6twObjOzUP4K2Vyt?=GAl{hh^`aw{n~Ido6i5k7uU7Ny-=3BWz#pn@)eU zNhhad`$Q8^q=NJj8%AJtFKsWEzX`C_4Cky%X53+~X?tw)GpnU*j?WNya{m6Zj2l4n zm>feq{eplD7$7w)p>g6cS$&>je><<#>(#%1>AsHP{989eDN$$I?!Te24o`$0$tUic zkof-5y8J5cdYdozg>3p0L<$e}-#uV$@;O03=K(X&esEa&?#T#mHg7O0bJ{v{UCWBr zweeNrAsXE3`TOrp^)3hejjR0EuONl;(&IXnZAsvlpvO8!ZmP0=E<4l>4pW-t-n~9nHaFl;sa~qefubBS z`@kg&SPuNS^fKd|Y1m4g@~biOt{cx5%vR)#HsN`mKj+T3)hW|2>qG@uK3(R>19TXR z=RK2%nka^OiDo4%jx3vUihhZAi%9-uJ?VT`^2((d_E5)zOIRQqTiAi(fEij2ft3?1 zw_xD{DZ8LnASf)BFoMc@mjEZ#BfMG`<_lI$jU7=m;X zUB4pv18yUbfz2VGcmHkNueL)%`?`OQ!`2#)t1Z&Z z&7IG3=YaU+${3T{)I_FRN_xuvuTS^I-P&X5@@eU*9lxRRO+?!!_cBy11HrZ?P@&bn ztRoDN_U0s*J{XOZFp-!rSzPrZ#Qvm3LC2sfQNo-^Hzm;6O<2?DAaNTd;RWh5pa7(Z zLt?^}fWiS8z{(l)Gz!uSl0#`b6YP7eyLI9Ymy{?_A8@RLaRRbMAT|~Uq4=E$^EXbO UY($FrDD5Gl`$QzPhhTmL0Qx$T-2eap diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410244 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410244 deleted file mode 100644 index 9699ceb49e667d0fa7e3b20a74341d4ff5cb04f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7236 zcmd5=3piET7eANshzNO1Gp3ZTR2U&D3Ps7A zFdC2IuWqO$c~**l425C#InKS`!S%UDzOVg#>~;28kKbNv?X}lE5Hv9?pGki*OO^C{A}jw6|q2%&W;MDJ|Hi_)`5K;1Vdg!&7=eG0v(#e%%8XdCU0Y#N|A^p3?Z& z4|a3cwhk%>UzG6WD|uPnoZGiTH_gsxRV9DeSiWwuzv<1>j~@_nU`xcr>Rl5SAsjqY zkL+(EnhqJcvd6sb*5KFd9q)b`tHf4(>#p7^;ZbKXz@n2;y1UoG$r&R09L!BCkKw}0 zN<}qhzUo>0@mTY)XxNXopAOw0kj1+;?X~f;HpyMuKu&b-&C6QytdnZYyO?K7|5{#JjQJu(!I+&UmRW4vAK_)-xz;o~8tPQ#WV!FY% zo?2bWW+&FX^4<4KVMSs|lqosdCrRZJcMNaq{g7313HYz+%2oS1?;Qyfnk`m!2G=|nfpSlW86&z^ZZV_r4F=tEU5ePzG3$n87k&U}tOM=EJLoaeeg#gASdCqMTM~+f6Od4PHK(gzM_mL z4H%TO4YX)ndYifSkmrLiyd&U&kqW&4FauE6>bUseq+wh9ppmhcd5au@OV_(QB-M_?#4AX8>m^m!>dvsiGoBjoJ*5jGahO($Uj@ww$L z{VnhV$I3XJdj}{NH(mX?dNBSs>Z8IJ9KywMT2ePD-YsgzhAk1%~Bn|t(jBkIDObb2Gka!wTNDcNf_ zR^u=ENaSSQlSSfd&qP_dH*R@^+Qd!71Jc3$t!eq^m`5!^?1+O>9K{B&r=(g@;(*6p zI(wrm=ys)IJ@vejzFMc9W=s3t15krvVAKcut`jS}T1N-SzTsRz9}@dgiq$IWQ(}7SBvld9wikQl?GXVsTakc@PRUNhf~Z7 z$$3&|OQg1EdMDiUO=s2Edcr*S3}1)S5`rK1*zzx>+&~+$2h|U{te5Xd)I=?kIrv_B zki^NgMKZ`l@>io@D=RfF2&e)+60}UH8iM5S0D4mX5)*6u&^1ms4>v7!bv!{GETC)j znThkyVrpq_YGQ!MBLA2<*U;stQ>X+E#i~>Adhyw$fWSzLYH+3ruqAe-@j5z%Mkx`O9g1Y9!Wj$OBGlA`_9R~vt^qK`8$BViC#*F;myBImvXOwbLEQanfYr8RKvaN#{UfNPnVXMeTz-Oapy~gZmX4A9I+b za~BvBjGgAM?+x30`~}~C-y(*HPcXeP625GF$tY#${9FE%TOL@*7^=X!rP8^Ls%J_EIczXGRc3;>FQ+UxC;&N~F=AB?H(%@2v@IG$S)Wo+;N5`=I9RKrv6sf95b1mn<+Q zhG+jf!8RX%!F}hqh~dYcPTCVD+^Z-BZ!(LZ8RazX=U0YlQXPxPnsCt7cV+9$@1dZ6zn z`J72igayXLFh{==Z1eHg)VhJKhs?(it*w~e29}+6r_Iq{3x^GJ7chg#z;7@I^P35i z!jtZg`S@$noyPQUDa<~wpcnx;UpH``U?`B~0Gax2`62WSk79EKw5hmgu+dO+Sb4uE zDnEO@!1S53ep3WWk#7JPnOSg7%4O#ClW6@0Ry9I1@B_nhya0CQvyW-8F$)-yzTK(k z1U`54e46b{&T;S4>|+)%pl;USW+&Ww@ylHO5nds-E(ChD$l6T97f;4v7hwYkBM(q zLh@m@;JXL%o%|4xr+r67RAO*qNYonojfwt5yTj4*JyV~_B&O&E#>DXKe<#=`)r&b| Oa{WdzWY}lYV*M`yQN#}b diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410245 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410245 deleted file mode 100644 index c05484d31ab4add8d50459bd2e8149954cffbf0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7088 zcmd5>2|QHWAHOrGXrb&8@hC~z3n4<0Z7_IxmN1q!Z?Zq0CB3LAC1ii8(JGV>m90pY z5VA)2S40b?r_l1h_s+fZ?ud`^%IDMhe8xHVoZs^OE$4U6y#RpLbg4d-V@_|Wp2Ux1 zi~4IoK2m*w} z@tZM2MMe|cEZtpy$}3!=s&cs7j80VVlDQ+X$6E8W|3HvM?HBuy+jqUYDeWSM`W{vZ znw8#rHm(Tp{&jD0&yAdmBnUCf{f7dYQqYLjs@=h!1Q;1=LH$r|&L-^$VQtElCac67 z^PL`a2JCbws-Tv}5yF!GI42jsD4DZ2@2KeNvr1!Gvei5La(yE%f6DdyTBouumE7*M z(fXK_l1${-JAm}%vx~WHD94JL6vw}Q(MoRdYIo=K)9r0_=}Q-E?kyJVZ~4dr91QGNw!C68BDG)MEo~4)Jr&)Rd)r zw>0;h3pct40IRtGZWDI^XB7*Q!*PT7pa#ZsKiENY3&>t%HF+gDW#k#`XtVlv z9SgQrd#k+kbLUb~%#uz_YZ-ya1jx%n5po<2C!m!gyfw^7^?m-1PwWcLD~09CI|Yo( ziidkuisZV3lk%y-xxs7W#5*>=4w5R0E#cTjaZ~NMnNcYD_ldg34m_RZCOIU{b_e)f{9WXp5HgcQsNnjkX#_;4sfj)Sp)dt_;Q<4P-| zP(CSJ9iF!?uJ6tzi|tt^c_=C*yRC$DakoE@+l9TGUktRBW$6m_cNaQ(Oq@3?iv4W( zEYE9nSX+JxBo>k>S0AR~K9rf`a&=zWvevjtUiSW^6tNosWu55P3THY0`#W!#2bWM{p*!j`y$T>J%P~;_Q`W8gAAo3x-o~I#!@;gBEBsOV^>ds)OA2~y8(aT#&d`+xl9?PUT|zH)q1XxfKz(=@zIrz(rsfb^}_$9|8L8guXLrBo!AR)`+a^|vYIt+bj@R!^zD zZd+qs6h?NlXFin2u>Xee*LNPZPTo)8y%iWjPJiD^G5K{{{kuc1_a2@Jx6Kqn za-a;QM+~C-Yes%r?ZFWZS^;kD|97 z3h@E&7HuKi3YOt?D&;6{2qX#M;;R7wscdk}kS|Wu2cgIuJ5>J^6_r#JzzJlI-jhttp5y)OmsA8A zh!;F*HXx-E%DPQdh-$?Gu_MI?jX^>@!P1;yqzAFk8Z$KzNQetX$Z-f(EkPV^t82uX zi%-}BjxB6TxwQU30JX{7kr%-7MsHz|2g)r}CMpj*@y!}Y1m`ZDm{ykoR6lr5Ss-gTaE_i$ z%wh5>m}5*3cGO=#8@BK9*W{S|*BHV+nRIuA>J=1UXbsK>CSu8a&4Go3fBvmK*qnp% z`oG3$?tJonn6UQ!s5k**qKi$fmY1=XBt=yk-dI)8X8Tzk(Cy(!Fj|@G=6(soB>+CN_i>?l6X8hIER_@j>$p)<0bxVG@(= z9Akp8qyD1j=TCx-p^nTF6LjwWh#0~?!PF5r=nBlB3q315l$n^Uj#typ1sX&5rJ2q1e+1TBC*Tun7tVX$g*i9krxrwwx zN^MtK{|@8mwFo~Gdvad~s%ysgLXdEifZ8BHdpC?m`OqHYFw78Lo$mfg)9*wze~C~s z-%aU3hX(%#OwNaQ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410246 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410246 deleted file mode 100644 index 2e785b821951e458e92323ab3f4ca960c8de246b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7160 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410248 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410248 deleted file mode 100644 index f074d88542ddb802ddf9d1a82b6523417b262da1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5928 zcmd5=3piEj8eSW&HNKJCTj3Ugq z49O+u86?%tEh;fQ$St>Fv`0dHSDc@Bdrh|6Shi`~GjOe=P)I zkD1mQJyXqrn@^jM89R?m&0Y=U@Q=}m#$ zewmbs%Idt?f3iINRc%gAwnPydZ0lcDGRiiDWd3eRHxyN2)tl|JPFB_&th1e34?R&+ zYn|905dxf>Je*po1OeTI;o6%?>suZCiaeJAaR?)Vt%-KtzA_DZPh7R_f*+ zLMa8&FIb~Og!APYk_Rnq&(*nKUsuGEc^z(140b{AceRY=i%o4dWnuD{UxyUcfm z^x1lyt=HXJsXGpbD{87-emjQHW~Lo1YyyR3YLkwIe4(G%?AhulN;m5M)uBI&6qXV_ z66B@6!Mr+Bu12Ft`EVG?xR>~CZ!sGaf-F@lAh!zq_@I0xrHwIF`ELi$s1%=yEl0Jt zOKTZ4ymIStoA_j>p2aSM?=IUYY{}T5YTh5Q&a0AFrJ{Br<<;ZhNkvT zz`%Iinf8r&A0PebT85tqspLhI3GF)he&+!lif;MFsPXb(Ga$%EK4?KU-3wLN<9JQ8 zy-&j0)0c}TUAILZS@Vw?FP&k!qnM6Hu5$d%=5Z*+mz%E7mPQB|R(eJ_8$+ut1RqSP+tGBImVpyy0HSIN--2d(ynQi(9Yop5K1G-3uj+f-B5Y-dq^NT!( zHSfas(7bdcT+=CcIdRG`GjNkm?tQOjt3Rp&Jk3L^ZCYL039cbnZ65)7d`|E*(jlDJ z{-mi%!T9=wN__W7np)l1h?aYg@CBPB%U^t4tsr*3NoF9N!62Y^L2Z+Iw^wBfSw!w> zDBtE}qD2T|#5Q<`ju$HPnOv?H_WvxW#FI!dGU_}sAmdXjNb^t>$&$KC889ki3{h*s zc0pTc3?!LA%G!x5uR~O~x*Q8`_RTt>;(hPG623;4OkearW0W9qF@a!zGN5nl2X)Z_ z?l(ag$%$zVyxu1uTTB)goz7r-xYjjk)lZF)kBBoPGVQWdYU2GPKIiD5_CYL#KOqm~ zf;E_?IjQp6w`A%4kr9Y<{9}qNBh4|cod5KUR>Ht0we`tTpM?gfs0XWkx!PtTE<{SRPfc3qyr-!v?Skn;1W^z}#1A+k zghR1Fhl3e~gT(@QYv4Xr(^S>M$)K`ByBg^u(1d)ArnXi&Ids-&do91xe|yp)MWC2^mkWtOoX036i@s-hP!W z>08{#-0vZ~vy@OQHhWvq+)QD#$IYU<3-d{v1q0BWd=S9pB(?_g$`9%f_b@t^&M_h- zZDxN1%X17+62Vl_iQ@!Z;7G0nT1V~`^bH5*AJhnaN&pT4@T$-?@W&%2y%oj;v2*hE zv0?j=e8FD%D{6@51b0S3%NO?i;1|chk;}#e?}vZp ziP!T3PKWCe5Q_o1IAJL%rqN9OE#ZtoU(wAlo4?nprHBssYlL2teQixt!u03&; z$<5?)dK12n&FRf$#=gKmj)5bWjg1=v4|pK{QjUkE&Zi<7Wt*@!#sv&0 zgX=FI?5nrAPMlnZePk^&y!1a_VH%7J5}j4glBDuCzwGbq$@zZjhtp2?hjf`(Z1Z~( zW1|zN7awq#OTL?eUR2Hug1rLYPZxxZW8g@Rb@rK@d-dm84)qVt0hZX>oZRt7fd4UGMxRjQkdpE z!+HL`gNuV(AwVovxGU+S5ej|DAx}g}rQLp814{kG>e4ID>RK6O#wt;$2QdA`-u-5< zH5mJxb2Sg&fe>O|c@*|7r~v50?_k`4!-*rg%ky*1)4Ly!m{eC76U5HR7x!%Tkzkv1 VzgQ+F_&x8hsNwwk1-Iys_#eRif7Sp1 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410249 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410249 deleted file mode 100644 index a96bed5f947cedbdfe496f9a79a7f26eace8f5b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5132 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 U8ztcdYGYF)4l&XvJl25>01i*~Z~y=R diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410251 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410251 deleted file mode 100644 index 3b0f0f86fcfd1fd235a4126d0e0828aad80f0274..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 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 Yo*N`?qa?gQ{WEIBAx8Ry#wC~n0IpW#!2kdN diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410253 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410253 deleted file mode 100644 index dfb813015cb042c177467e0afd9cfbd2bdf05442..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5088 zcmZQzfPifV>i=}!`|?>Fd2%9;F(pA}p+d^i-n7>%-v7MgJ zf7#!e&S-sq{p$V}rs)C){nqF;%AFQ?*8W7m)7H`Gsp>w##%DU!0Mh~ z*-z%Mx}}3`N?LTf8Db*?BZ%G_E3j#It%l##16J-!A8ws+l0UpT)LrICK=r;RmP zKqU_HrW|{OJ=V-f;G8~L=;h?%#?os~HRkLRaJ-tH{C%5sm^te+@&b^bHW zh11_{S7G#7XEJ|jLEMjjw{>~a%{~<>ls6}tte^C5&Uckqoz0s+Xzsi8JkgOg?XzCi zl%Qhw5+}!Fg4x0|+D;kB-qB{sm_Chl`|EV2f4k}3rKX#_ey!JzzF9&`%lkUa5BB}_(_@d`_h>=>>ghbQ z`5$iWmRDbB@^hX3sf1@+%Gy`{*;4-hoQ3ZEf}2U^;XN8AI=w$XF{J$an;I0;z$JTn zPGXC)!|ZFtH#7LlT^?RfeYQ%eYvI&4O(jMmfhQ-co-)3w72c)f@t8gO@ivH?7#Ik} z6;K@u5Ho?)EAg%W@}qlW{NmaCGw&!AR<^cm7dLmY>kd<5J6*UZ|2YG{lLIge4gr-i zgVaL-IR0Q92QO=nOTUEpPEURtvr8&j_RWW;i?$yQ3ZM6KPZ4cBe*~mX_G~IlIV0Fy zVBD6fZIP~9x#D1>&?@unBFmpXh6@+&shhki{+p17`sL`gFWEx3FMc|4nt>$0d-&Q0 z_qFS_1>wt~dFq%-6i5&Edcf0)lV2qdPJMsJDr)cJbw@afA6@p=*5`%@+ximi>Q z+WXqp^5`Dp%iJllHfAyv>-qSB27<%V@U@!pZHd)aj#?=b3l% zr0E1 zOb`(+49xD<2cS9_p>B2fdswvOU}9&{UuK2eGw~-4Ogx_bib%;=e<9Yi|MJ8;e5|Mc z2Nk4O+Ai6us$8WvBlqgd>)v+^dYca_*ghAtc?I$xI9zTXwD{5#|L^Yv4doBzNpA}J zHgeT}IAEaid%@B)melUI(0p-oz5_5w;GWD*hTQ0Y7kw73&iMU7E3$R)s!3cH(Fdcm7IMAGXRxmfdX!(j1 zg_7AzUpzNSj*>{@VZV28i@{p)q_dgt^|!Y@PybWe?wvE~ll<2g0{>bA{m&_%{>-Y+ z$O$xyCFS>bUYi@!e!MUcZRI(3@pMA=;*T-GUNP0L<=*ywDUpX-n(`kAKz2js=J%)oNv43y76M7m;NU%zJoG;Qqw>SKlJ1<^1|P?>NQ;5dTwU~vGoADGAMpmL0$ z@*Jj)NH^Kg*i9g}!@_H@xs8(W0+kQch(mCgAhjL9(YJBUa*h3V71hqOql7Aasw9MMh*iBf|=pb<$CE*1st5M<#iG#$1#~LUc zkO8Euhn6WwX%wUvSq^L#5#dEj`44jktR6siFR1K=mnB5l3rg3pG(@{Fq0CJvVUOfl zBql6KaOO3PvgC^lLu@KX?jkndSAWuO%u_kZd}ikFRCzY@Ck<|;fgZt76Vb~NxJ5t) z$X%fDJ`NKk*ro>7-8^?>Er5CsLG{D5f@vfVAu-`fP{IKy3QK2T`+;c?;Z~&ZCeBSV zS7_`eklSJ51y7%Y#BC_$2#Icj!~r~tPzn`N;t)N3g7kvSM#;~E#%-jfFR}N0+hOU8 zR^i2fT<#IwFGcbPQWTFVrkBg_OXMm~a)i$_udl!14lC m#-XHtBHaWW8=|S3u$C8t#BG#>7ib)U8gYnTUce(A!~g(J;GgCI diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410254 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410254 deleted file mode 100644 index 5338e11b07a31e897a02b63ba0122a862daca410..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4932 zcmZQzfB>E4$2wiT{&%19uCbXr=OxqD9ShC2U9^t;tWbCD*yK4GKvlxq4AlSWy!Yj^ zIP&B~9%D*^%tD2frM+pdSG@n5m$y>UtnISwm52?D>X8rmCkoAd>t!~jZ*9kAzF(YP zuC1J5c6UKGB`rGL0kM&R5ky}t%DkBr@ZB?)efFalrb1@#|G&6AM~`j)>WxnF;(yX* zfJz(`vhGJ*;|W{5=HCa?6+cdTJStGToOeUx+hzIVuUs^y|6F+4k)uO@kzJ(W-5dM% zv%LOxCSWF8>e(Y4pX*MqzM8|OapSkq8C8L0*J?J%KdJt$(H-IPE+#U^rf~1+ZJF)` z+k$HIowYo6ES>y!-HaLE?lkiMSh?wlW9ardjB2Z-+72r+h_;;LeXwow@)VGZnU7zP z@C7lT;1noqQW$)^9YC~##%B*LHQnU(YrS^#%@SH#-q&G%u-Pv@D< z|8Q%!y!t|upX>BbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}R5o738db^%i818FCo6uli$Ydl1i3+^P%aY?T3TH=e^uhL|e}vVc>Ui0EWR?pi*$0 zf%E_Yhz;fw)X%`c22va1Z3xoGAh7MbuV+cpU5)uo=Uw-eTBhGZeD(>*QFZbWv z?OXsNV3D($#; z)iY&&z~TFT79m#qB&K}c*X+x{*tP&@?N$b+@A)A6ffx>e>30#3!*a*ZS$9@fiY7&fi~_aRX>3lVgadOAwF&1L>!(C0ESiEA8F-D_?JN6o=cX5{uX683Go@ z>$GMrzV;cYPNJyh7EC!K*nhyV?3nBrYjE((!Tm8$n7Dujg8g9l+L3w2 z2E{YeSX8rLseDV}G_(WWp6h@EC&(AWiJqqse3(U}cUG0uYG z0xM%njqt-a#?49V6!v~NVs|dPi@&llv7-CNgzL{< zh@J!akHtmO!X{32R=59w`+loM;+l>s&n~%te8E}!wxF~LpR3)WcBcFX0w5a}CX7Jt zFQ^~z zR(v}A%n7xgvR&Woa`!)o*m7zMG>);Q(SJ}mSeS$AHZUNfEMQs(;_iRX^21yB#D-bGJy z$d=%;4`vmJhSb|o`+<2d6Do-k=ES*4<_eA7gf)#061PzjUdU}HaPT8V91;^6GnjD> zi$nA@3epRb1Enu`y+dMn(avq8xk>Cj-*#B~qLrH%ki&`Sb}N!U;4uVbV2e1useJ2A zPfOj~QrU66)jewGTD#C01>4>ixQBTQ#$0nPhU!NzFF^e(7y#t~ly(;p{WD1W8roKZ z83d!TxDzEU6K8(P9AMbN>sgrDAR3GLSo1Lr?4iUT7|uo#Kw`puie3&A%9F6P1~!Wb zzmw9xhB*q>&qj7HN?AaJy}+~sk6UDOz;+-BATeRqW7JK!!vrZ0k>Ms3yOB6ZOp@IM G*8l*&y`n4t diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410255 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410255 deleted file mode 100644 index b089316285603351a4aa78543a163cac98fd3f3d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6208 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410256 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410256 deleted file mode 100644 index 0f076b8752f11f1c11b1056a874c1de967f62eb4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2864 zcmZQzfB>m&RVjXa8>R)g#0d00RM!suK2mviD@sxAV@g zZm_#cIQ$4JJ)ojt_?K~|(sQlodzHbVXX1U=uQYeKB)Iz2hyF?y2j+P0wbBB;mH!&A zrDQ8wrGacpT6B6c#6|{25WPa>ti+zVrEI>Mv!bKdEU`YkO5Z5cLe#cLfA-eXxgU&y zN*pwge%Lkj0PmbIo6emK=6=f`AKDb=m$TJlYxb<<(5(tQ59_@46x1xfT)F6c$exlT zChN_sLf3BCymybz*RU@6P_~5^8NId~E{T1?F7Vj-Gy4VSofog=e3--5zQQfyiR`wP z&pG>Foaqv|cX^j*pxyG@j~EP2`W^SGdv&j#eV2XuqkIO@mJ7TOwryUX0&+3)@e9&1 ze?Tk-Pv@D< z|8Q%!y!t|upX>BbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+})|^&mzQXpTv~U`3x|g<>%ijdpYKC*xB{S}@*R(x0`I*(yHOFTNJUM@VS;h^Zc}$KWo-RQ^1`MR1 zx|Uoqi?6hI>#uyh$x$3`r%EhdmuCoA7_ZZsx%k>=pgM`7np-gCj9~u((^$f^m(wLS zI9-1$e{-|8N37D7kn2kNtNuGZ-|(gC(runQ)>D*zYxXcSbqd_{kt%p-{p3ui({stB z&)VEx?+wq%a{~YH0)a7QYpx%uWZ-vl z0H&vNF!dlkKmZRLg8CU4*g)z-yp6yb_3r*#^~uubMv-mA+9jL#&xLwNEPY`WbKg$X z`{^;L4>nNRw!#f00pK4zB6__yq+>q?h@YEl-je+;ylr6EfY0&h3>s65;BRsVo`v)&~yt(ava`c9~mz42w%HL#`Nv;$#*Nr?NQOmLVn1HD08)`o=E%!p@7(sa+rj95#oxb~r#%_Y;S5SBjHn&j{ zULb#=#1#?;i3y7hoN)*a6SVpT7QY}luvtXJB`J9e<|tSmLv}AE@kF~YAwTWF(jUyv z$dQKZZeHLyBPu=dKeAvUtqG>Wo)Kot%7iM)CT6?ltLE&x2pd$a{ee z0hS~GfdI&c*~JLt{(@QnvJ0ggA)<~E)0h~Y2Q&^;uN46G^Fqx6Q!q<_93&=O1unmV t%Q0N#2vKh8zXGfqXzC_dJfft}LE<))a)d-Tf!Ze2h(q*p1Rm)i1_1ji>u>-7 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410257 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410257 deleted file mode 100644 index 6ae2724bdc3b942b7c5f468073e91103d6bd2392..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3892 zcmZQzfPl#Br6Ip3H*1~9eqmuWC%Td4U|Y&n-RIvf8i;UTu-@nnR3$96tt!QjZ^N_z zml%QGhYH)LI0~8-sT`Dy^xAl4|HIey8#;UEhW39KEPi$Ay72ca@}Cy)9di7zU8Ul^ z*83e#-<}8Al(gvdOo)vPj39bztiYz-wHkg`4_LV`eYkbPN&fKWP_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgLwCW&)`%(3sd78~lIS0!emfwlAfs))y3Gx|$yd#Y)dO^VaWZ8Bht(=V2!q7!>CN z+2D8s=>q{^e8TL6iSq)58AH9n(hMA`FLpFY$|h_TmJw*=EAw#>va?XOHM;NHbE9|f z9dlivs(mi6L_z6`7{gH;NpTO!c0j|(!SaL8d8s(2%Irkbc13wdCPE zo|*b4DPLTVuzk62I{ncmot%>G6HQWqYC!tHdI{PGRrk{Na`~G8Tg`CJx@5*3_L{cG zCO@-Uy5{%{fhXthFUz^$K#M3Vb$bf+%c% z3*&WKGZ$a`3{uBv2ucQEzzFsqFwbw^bv$N;hU2m82YRQ=tmr<UAhRLk zL2LG`X@2~in?)l}>H0Jq{tMia2Cqc}82FtW7`PQ1f$Ap%F-lkh`7i(vD}maJ**X@+ z9!+|Ua^F{-7r8j2E1w~xDCDx8Ty9&~gE=q_*8evzj-B|g&f-d&$H6e+IXj~xYn7*d zH@s*wYxS@8eL_HW;vQu$V9J@mZUOrHjmKZZ%kQ1JRVFd*zZIR4MEAD!Ve?m8K zFFSgCnYI5>QSCsj-oM?-O^&`CH&mAF_@DeqN%6<)k34Noxr`P|r%X3xxL$01mL*~J zUzLjO4V*xSF*nBi*!w{KpZDGmUf%*wN9#nM^p;Ibw!0`Rm(syK7b0Xe&ppg@J{XN;2@(?~3yE_$4^qZ4!0b<26m$V9#|SFZ zVd{uM3|qwORtI)^MUCT5#L0Y8%TO!ZU@m=+|OWs z_pr~)_czn`S6c+^y|T*WcyCa&nAvGf_zGyt|Am4i5@Mh_P5*%`Y~t@Pi%Urnjv!8hbvgx@J& z;)13O^fbx~Or!sxaD?UKmw)24IfXWj%KuVZMOt>_zGzzvK=)X9q hN|Z1s(oH=yb`#b#I!N3`NqB+!C)9{TtZ5V$^8hJ|*@*xE diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410258 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410258 deleted file mode 100644 index 75f90f17a7039dd3d7d765d69d3bfbe6af34cba7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1528 zcmZQzfPj}-JHJoyI@U3Ttv5b)xA4W?8}=UiAJmY<#}Sy^cj)RCpeo_W>!l&TCpT-I z$bMmAG$*=|{V9|pL_huT&yrU+^%!d{9`k_&W8kY zUlb}7ZvPLmDQVH^`4Af!7(w*aqRg8~0pC4y*=Ij`VJc+y{{M^1bM)Buuioe+Fa9T8 z2B^eAd_&C_UQwkOx&2Qad&B&1U&{;+%(XY)U%oke+tjd~=}+GDi`&oDUJ!pF+;fLzRc{DRDr z6Cf4@oXP;wDGWZ|4j@`V*!R~@k3D+dqXqe^r}NC_ zf4H?H#YbvCdgO^eSl({6_eYAS%>;8>tO=3#<>nT6;_j7%P?hk@texMdcpdAQ z!qyufyIc6;?hSj7{SRtL;^PQR?mKjK3)A2K;gK^O6Q{k}(cWJz%J*XN(~WI4{}ZP+ z$27c5K41v4DQVH^B@i1K7(w*bSb3?9`f%%nll zC;6@}l*hA)MeVlUyT5sF{k-36FON8Oh_+njeXwow@)VGZnU7zP z|HJ`eLBOdDAf3YCeb((=9z^MieV{q)$Q_dQyWzj`{) zZ2pH^yXDmvn*3a+e=6bGma_Jhf3}qWKWCvkzu;z)d3cY8iB9j&PYfyl{-y@SG;qnD zo|D+3>@fRU@y!hWa+inKQ=hF;>RLGUO;d@HNZ`rIs;7*vYK3bH6_YL6g;HzN_3yy)5YM_~EDeukt(GK=VNUVMy^0e9BZF$9JsSQ)$P&tDY(I0}kK!vk0-; zCo$#ozGhzr#$9@fiY7 z&fi~_aRX=`lVgadUl5Q11L>!(C0ESiEA8F-D_?JN6o=cX5{uX683Go@>$GMrzV;cU zj?qvTrkoM%KVVq;6!2DFU1hVU@5yR0YrdDiRNBt#ci22&R(-$y@BT}xlm6@qUpCRQ zW!v`~0>9sVcyc1${0--`ppWmrN8S9se{(h$&_JeDXZhb>3P1RG&V|($JJ%oeix0W2 zDsXB4k*M_4ZYJkBK4441VF_VD9RbT1;vS`m2~aUmyf8!44_Js`dShS^_b7Y8fUE~< z7MMbbG>8NvD38L_5M@5deULN_(*~!pm=E#;%pbJ0hZ28aI2%a-i3#^6$Un${8O(u( zBU(Al0+a*AA-R6XupdbPi3xWOv2KH_BO=a0?mq#ufl&Fxvuv-??ffs&dYN_lug`oG5@BjwKV5b5FU=VXmZxrdFoWgyFR41P z-++1YKM)|fnGwkS1(rjk;Y(0H;qsD!K}@61_Y}~3pfa-7eph40}>Oi0vVMj!nDyGqMT#LqT0=XT8QPTY&aT_J!1*-R`5r^Qi0I8gSMkRy- E08psyga7~l diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410260 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410260 deleted file mode 100644 index d04eb76a42d14dba7466dfcb084f9e61c6d99cae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2736 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 Khgj1nEam~_hjCB< diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410263 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410263 deleted file mode 100644 index 8effaa7aec85513ba74c93f6630cdc5e40ca403f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2428 zcmZQzfPmf)qVI0%GVbk6-6*yB^o|ZW*SB`Y8U~Gf((da1D9cj;suB*p5xS`U$EC}9 zduE;&I%vyOZ4;q-)Jx#N^2)SC$*U`RjJ^miUBCPPo`WWD?=`Gy6MImi*!nXg(Ufyp z^i;z*#VH`0k`|rb39*rZ5kzl|71*@9R>SY=0W0^V54TP@$sgVv>MnC6pn6{u%O#s` zpc02A`!|>TiCOBm{-dhKg3i6`kK}PWb>UQzA8rDx}K^}G!0nEREy^KNPH`TTC$ws#M*vI9al zYVZ10kfXPhf7Z-Lv9q0I&TN-tb4W{9UH0VD3&!lJx%LdAE!TM;Y}>p%1>|Dp;};ZI zKny52l>ua=F!*>ofM^Ac&mLN8y2ufzOc-(NpH_UL_&7UZv<&NG|; z;nr?>^@S!s*Xf^1c($diedV7m<^RuF=*};=nPeW`qhX@c`|}e+%D=yXpZ(%!AV^7ST1ak!l-v3OmcAz)#=PHX1kYo9?% zB?_b(Kr|3ALfpyVaGK-5okt%6?lOrdY-=jaoXo$T_5CehW0}d%qO%GkiwErpZY zS*g=UDbF+S|nkCfABh^s*%5A|1HoZ)T%rh*pyX`AYeE%x9$S+D3ukywG2_KT^ED3cE8-&y)c2|< zHgiJlO!*H4KsGE)7=hehP&rW8G6VC|H7K8mw8tPWL3td?Ce}@`JV7fr!SW|4yat=wCU8%SzwA5X_QDedC=HRSkveraT`h+CDBcwGMyT6h&7GE(gpzfvTPav diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410264 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410264 deleted file mode 100644 index b1e18e3af2857bec570265a0680f14b85518f5c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3588 zcmZQzfB=6hp0tx$s%I{_thM!WS=-)zxzgwRSJhCzr&d$;DB4v6RSEZg5Pf%3mvL`r z>PD%}r+0M7xxTeC)-Y(?lXh44M_HcA)Bg^S_g;@t3py|49DKCxeBfMzz9@ynzb`^v zxt9swtOD7TwCMCch>Z-4AbN$$S&2P!OWAxiXGKS^Sz>*7mA+A?g{Wd{>x1jpH7?khzop4x1PH7cioka zS=KvmFaBWVcFttQtdJ{{_H&+KtXs#i|H7dS+I1q^^(yLD{C|=;W1=h%Q{t(=YBA~4 zb^hl5nBElpCZT?Vtl{(KFukkUiw*4dz09`TYC6?oXAgsD%MIQK+cqyx0lAp@_yq-4 z9S{owPGtb;6b2t}2N12G@!3O5O*eV{TCW{_vxJtG_jQ;b?ECAd#~!`!(SrQd(|Km| zKit|aufEXa=Q{mU3D35awXgiMrTqUn3*GqzH_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgLwCW&)|dTWY#*YL>^Ojs7og+Mjy1`E&Zl@;FsB{Ue*3q>X}JUS?oyTLlb*BS58~ zI0MHUNFN9QowRmE6Alca|>O+>v%Y z>{-Xtl7IF8Apm9u*gjyKt8Q%(nH=V-8glMJ%<*1^rAeNv*8C4HcHerj$l>dq2Tq=a zch}u}H&K#NrepU8uDOzG^UaM9D_XzrywZ}(JM#`d&^)l;x~9DjF`qd3uJa1vgpdih zJ%zcHmLxBlBbeiK^}&)hpQ8*6>H-YHei;mmVY7jH(EWA;D#lSzTwrBrVql7-2CVj_ z?d9?}0k)dqoOQ{JJM1-Wk4=7NwRFw#83Iqv-(Qvi($C}=;u{$RWWYfBscXph4DJAnTxM|2C0)MkZORcXN0&Dm=6Tl4soq6sy_aqWlO^r z?b}m|d8%%(bFntqByoLvlDg}H^mf*TrxrV0{jsy(_hi0*>DLz-DVH0nk`A9Oocs7Q z$i3h&F?{XFJY$36nQ1Jl*{@W-rEqdPD|PxP<$30vJZU;X*bt~Lg+V~JwWrdKdsjVE<_8?U?`IKWwNGNo=Y7q- zK!r>Jp+NyYt{^QCKuowW{rb=VRn7=?tAhd4?+M$ocWkb<$^2ZWa{HD-FW=l%>(W&; zHC|}g>iV(8yS%fI@O8@EB`bYoPQ{{}*=u4=1^#dswep@=&urZf3KM2#C#R(oa_40~*$#a*-9L7evD>L1n^Kfa4O*gXCuhnEk+fxf3eK2owXQLoguDO*@~^*i9g} z!@_H@xs8(W0_7KK#349Lkm^cs+;M6cauv2p%`Ka2|1|2x)5m7%+0Xxe6@Gnz@9#m; z>=nXbMZmm^C5`@q%E7`Mo<<3mj|}26zDck$au(1W9;jJhiWX^IqgQ0&)}^mA-Z5pPc#ivV!)8mX$EklFr&!%RDN$DF(e)jg zcEBwuARCr^Ky3yXfTdATdjkvzwoibn!1V&8jRMt$pkS6DM1b}pm5D@}F9XyAcN3CX za8DqKVNE+Uu!jh9M~)({7!V65o|Azs0S5v zKmcSSyO$Z}CXhNJ>;V!Z diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410265 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410265 deleted file mode 100644 index 50350cf53eeb6a0b0c5a37d13c85dd2780b4c114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1476 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 MHUb&g90HRE0CkqsPyhe` diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410269 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410269 deleted file mode 100644 index 194edc9193121525934d5d4ee7840d8dbaba3177..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7072 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 Da7K%L diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410270 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410270 deleted file mode 100644 index 5ab3583ffebc20586f1357eceaa8ca6a88753361..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6052 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

GHP2rQMY*0>pSe3pBxS@O3HySWUrfK7Hz z9D6n!dynfO3Y`Jo^IuO*vyI&FCQ3`icd-WD+nszj`HZn6J?Gq({ZQY@3Z^K6jEw~$ zJ5BFIb-|4!!iSie1>ab5c-@~X+|64Aw+>zqnhf5IbZg0)zIVRRvtRrCk=+$?JJf0x z?q2*?yG7{{zqKW49kMgJiUnSz$ID#?Ho);vxM%nNxZLHRA;PKsDSNgyHB8MsVV#mJ z&$hpA(MDxvU{eCjBaz@-V2@}4`J4jQ-6p(o>~$KMqjULqGPYKKVw2E7sN&W|@e@Bm z-%v3B;JXd;3HkzqxN3# z9n3HE9eh8|SdR83p3uP5#ITJMlU$Q3o?nxN3C;sCPZIBS2z?;GxO|Qr&0|VMa@kk9 z6Hnga+ATY#xMySk&68Xw*RAn?c<7b9#=CGo0s(gLXA*cE#O%Vc!+5sfekAzDD$yf< zRRZSVzUTnxHv{hrOWeuGs#s$**Lbd>{z0y_W11uKUouSP*CrVg#E$dTijU|k!8Q@T z;NJF2#1Q3#uwI}PU0vlel)m&*g~9<96P`694C}x2G2`}XZeM$X_pSA_cQ5VLDgyT>@*rK+Gg5auBiE+Lli8GcjIa}ucI-w5$H zRf4lIBAr`A$Ii!vCo_3HnAQzgSxcxRF^eRjS2O0eNMh;lnl zOzFB(7EnSdrm8epmR@a3p!T&8H z!E**LVJn`a@Jx-01m|9aJlGcu)&p@Lye}+?#&->XCmYHgcd>r zp(oad;mFZ`baxb21rzMgLbm?-vCEZ~p}- C140J? diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410273 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410273 deleted file mode 100644 index 92710228022088d31967d5a7a3629f3f836f72eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4864 zcmZQzfPiLAO$nd)b>`;wwpVVgpCH?t9J~2Ju92G8bPcc4(*ACsD&gBs!s|MF?v`rJ z^nDr5Z=P`M9mAU7Jr-$tldU2iT)LK_wn0fMUqWfllJ2sT%}uj@rkaa0mArkF7`paT zcGZF~dyq{@i%!3R*vP;LqOTTZ-b@Pk?wQLz`_T(iA+z`YUtFG}$F_gI-;jtsx&)WWqV`BwiEA8esl_vSez00#?hR6UGKX$&vF{yxVrZoQMenq!o9$x z%TdG1zASh0OP@8Lwm+zf71RkElnf(a#yB_4ufdRL*575HZM;BxtRI*1qI;+ zAQl9i$^go7mq_t#I4J$m1x1^KI|^UUUd zxV2keeWA(Eb^50go^2^>U-@TC`Tuhky7LQeCYgu#Xqf2q{`|y{^6zhIP)q}t?CCj) zEy@nFuNB|S;4gQ1cs=#mDy6Q4Q{Oa|7>NX)oUD4v_^MWTmy*Y0_UOmkAZ}t{AQV?X zbu2*41X4ePm1~;lst-vM{A;9@{$*x8=au~C(|6^^jRVH93tLMo85qJwWrdKdsjVE<_8?U?`IKWwNGNo z=Y7q-42*3HfYxqhVESGKvLA@yAZgJVb|8mk@0_=CoA!Gxc{q<}roKta7uO?fU+$Yu zf3!&_r)2v?lT@G@kUp?pg7!hxy|let{wBayGn}(7nQ@1`rtPuG&#acNIX*++$@%-s zGHw9PV{#1f^a}zqU?Ba}wd9Ife5Jixf92~gofi()Hgpn>49G<@yIJY$36nQ1Jl*{@W-rEqdPD|PxP z<$30vJZU;X*bt~Lg+V~vj8L~agj(LWs?2!!(x$;^QqDSo=9>KA7GPCHz_9hy(>z|_Os0j0sz2EIqvQ}vInw|-$f><@|!`5WY2<<8W=D_%w=#$_+NLuFaJrTy+Em>*4|6=cnklo;Oyby z8a@dOmNEI)rg-P zp0{ge+^ddjgs&}FE@}Qm6SMq2#PqQaulQ&quoVfc+t*nNbMD3 f+{AN77M8wfGZeenI_O}CbfvSX?H8mxC;@6p* z+uL5bwSIzZZ*uJB2f0RSUeh(aN=y5@f7|;kTC~C7)%1DBWp0mD6h1UZZ*t3eqw_v4 zb^gDm4^<$Wk`|r*2(giY5kzl|71*@9R>SY=0W0^V54TP@$sgVv>MnC6pn6{u%O#s` zpc04PC`Ofq^F$I#rp{H}WxIG{XQ9Q2X1sLR$g7Z z&g8P1lz-{*--~SZ|9rW;fLzRc{DMNq z1rQ4YPGtb;6b2t}2N12G@!3O5O*eV{TCW{_vxJtG_jQ;b?ECAd#~!`!(SrQd(|Km| zKit|aufEXa=Q{mU3D35awXgiMrTqUn3*GqzH_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgLwCW&)|-!1w5Ss{XO{)-Q}_+`IW-3Yx{Q=DVh z600p^Wh2p5bm*Yh4*f?$f9`|K0{bDwKkzA2c^u!dYEPvd_pW-T%nvwx-_Ih%YM;cE z&-5n$)3x|g<>%ijdpYKC*xB{S}@*R(x0`I*(yHOFTNJUM@V zS;h^Zc}$KWo_;|<1`MR1x|Uoqi?6hI>#uyh$x$3`r%EhdmuCoA7_ZZsx%k>=kUB;~ zU6^u4u>XMhBwE=u`sv2Jr@WdX9*bYUIlph-Y754VQ+^nFJy>&ub)z@KzGstT|9(2H zR#BZ|a#i(T^zzKJlmGO7D%4!{XQx;nC(uA}Sk7SOnkKsHL(&BQ8fm3}nOVsvRkp&|0Xg})P3 zZYy7uuvnJwFFNDe?&nE-$`%Y87wyqI3bh5O59|h@f7zx#Zf?{U-}B_{v(xcA_fGVj zrRJHclWFjLeUms}SFhs>J<*k+ZAD#Yc)V6t-qha5@0RS?C-sTf+dy<(^V+4XKoglG zVsc(dyinjg{7d(*c=mMno`ALAA0KefoXZh$?T_VdUx=;1^bY~BbOUlf41mIn8Ja)9 zVnq0#LF!V83{cMlpaz(kV7(v$NdSonmj=fXoCnFr3^4nF_2L`iJ{bPs;KljrT#+`M#W@9TzX zD_30%fCMu}IRXoP5Df}1lyZb{z0ANMdlpzNLF#5?v%qW=k3wWo(l~ME+kPOye2^bt z{s6}t$XXiMLy12yf(1zci3tfXsDI!bAOkr+qPJ&3awvI*M89L$k0gM^ggXZm*2n<2 z+mP}MF>aE&p_CUSx(U=@ Rphg^m!vv{rhXoOs1^^LD?>+zk diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410275 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410275 deleted file mode 100644 index 5799bbe692ee6c991d517d5b51b372541390c640..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3896 zcmZQzfPmNWWy~wCHm3?9`f%%nllxNh5}izS7%fwN9m&oW@1V4<`7p@g%=n>}~h;to7G zo|oC>claXLotx$?R$mydeO#+wWouP1d&}Xy|81HNNqZ_Wh_*cDeXwow@)VGZnU7yk zmDvDdLBOdDAf3YCeb((=9z^MieV{q)$Q_dQyWzj`{) zZ2pH^yXDmvn*3a+e=6bGma_Jhf3}qWKWCvkzu;z)d3cY8iB9j&PYfyl{-y@SG;qnD zo|D+3>@fRU@y!hWa+inKQ=hF;>RLGUO;d@HNZ`rIs;7*vYK3Xu z%iF1@{cYM=?K@{HNjut9UFJ8-|CpI_b63#^2ldrG0(vKp$)`{M;oYe;BUC&3qeZF& z$Y0>FNbwJR%2Xc5cdXh|X~(^*o+i~x{g**oX0+@}3rOCHYSnW=A*^2PNC+n4*M(;scp$tl@B(Ige92BZ(Hm!N%6 zbuVo%m%j|*uW5U1@-wTYYmUzlcyj*!vWy!*^Ozh%JpF=z3>Zj1buGDK z7GG)a)?fL0lcPA?PL)`^F3%9KFkYuMbMdv$Aa#s}x-jL8VE+Nba>wLO>*){M*S~S? zy860)cg+1?uisDlKYiA`le?^W&TW`@d&cker8O7)4ffu8@p0=yTh3FHoTR7g{P$=y z(P+!N%nvjW9F`mS9$in>Kepcbh4GAgH$SXN^4T>*^6Zz@AB;RD0>8>{MoL#;^-zbv z!-k-K1_m~e7hq{;;|JuNdQSAN-&w4-0AeLpz)=+{r0tOwssUs+wyXcQKav?lGCk8b&aqnpiS zWc%+4OQv1!xbpX>mD%L0UH82hP2+xZ0Zn9Hw7BEi_4j=`6UE&Q?3J!qW-F|#_2yWQ z--a1>zXTk%e*oJG%100YOE)0*!vH7@n1T815lnyx|1(Hk@-0Bin=tLji4$fYTn@-U z4s(z=s61eR*$*tIKZ5z7^am{eplk-B+;rjC1sb~v^e99z|lpRiMWYES-Vv$5oCH<)&`oc{Fwt$n7AEl0FBC+fd3865Rx9 zn@}ST!Fd*`905oAnM8$tP22aYw=GSWTHN`TRjRUlcdSj(#o4RH9`NZe7X~ZBtm}}| z4lK+cg4F^Ef^ATs8m3<#8ld$GOdFg=HXJI55`ILP|1J2bF|5`SO>3z7g5 v6CR8pKOqBHUPey`Aic0Sd<0~J&7yKUAL0(|^$9FYXkjm;e}Uazc-Q~{^J^so diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410276 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410276 deleted file mode 100644 index d1211ac0b1cc9bbb18676519a04f03eccbc13457..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3896 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410279 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410279 deleted file mode 100644 index da3e54d5b6027ad34ed38ec76a728b665fedfe19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4876 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410281 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410281 deleted file mode 100644 index 02192f689091107bf59937492e26ed11c418df0e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4100 zcmZQzfPnYL?045Om{uhUJa7^d2$$1y(kSkH5;|kv$|YYmda*tLsuIq33zmJH`sk#R zTkieH&(im^H~q}=c{i(_)kn8?@qN|CWE-0s%`;jjV-smJR{wG}q zsKnvJs+!n%PTfZnW|$~{xGz$rdvav~^NDv%JyQkOKTVaq6#iE`S4O6$_Lf(g_T9z# zdiV9qw>vC|WB4MK=2*U5oOk`M*2`=1nf|F&f15n%aA3KEjaTvc9tG3ApAYqStGB33 z)ZNxS!RS!eJhr9b>6dDlcd8t@%<0B=kx$>QofM^Ac&mLN8y2ufzOc-(NpH_UL_&7UZv<&NG|; z;nr?>^@S!s*Xf^1c($diedV7m<^RuF=*};=nPeW`qhX@c`|}e+%D=yDr4NZo89>>kHLxatBx#Xo)gR6Ex-qIt(0skz4P0^BhgS@#WNZN2b;4DQl0dcNLrx zb$9)i&~tm_XO%E8wk-grq31C5P!GYwi=ci61~#A`#t?5Ku-1(?JWmHH={Z)tVae_P zx%={s%;1&KdOBEe@e5LFOzfMA$IW0FB4b&$6+6T+VQ3ph3TkRO5K~3*&4f(6=*KlzlN_J znP+TJJTr|&HT#vyw-iopXQfUbr998PlP66l2pa;`r7#GHon~Or0AkeilC;gA+EZ!Ay{n!n^8*gw_p=DG+9xsP^S)+ZkXr&m zg93b9fh;IUKXom+VisR%@77=WdXu9#+)kBPye`iWurOYyHFNQ`&tPRUrZqs7GeX_! zps%GDcx7f!Lda?hwVF?}F8VykIA-am`R}c*yp6&cCO$k@?V4EmfKS)9^8UIs(9>u#w&IC)4EsD1-5$xeXjgV9(VgyMH1%;%dCbc+=8f$0+w-$d6R zNP1vy2hmvE&oJ$wMnzumG%ZuEtZCcVJ*iMEW$X2};#{A*Iy2mF@u62x{VD%}0LchO zAom|s4wf$A6&DfZB?J5Vtuvry<|&{#pt2SYklcyHgiGT}17Q1sX+Q|75+!bkbdw2< z-2`$wEWF@l%ph?aCE*3C_oxwv;4neT$Ka@(82znJ$dz@E%)K2hT~oL9T>g9D+LNyW z@|P?FHvNn>R)oekdR+r*L%;wm%;9O2h&Bj=?Aeq#&~^+c9ipT~Bn}c2W*x4&rUh>r zCDKh6G!(lsm%(Jo9Va}&s2aDe1lBqm%MMJ-SiIWCa<-*628;630J diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410282 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410282 deleted file mode 100644 index 8fe66297d17eca696c3b51b690eccace1a07ab45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2684 zcmZQzfPf8WeRq3QceEV4{cSGq3a9tdG8ghz7Ck*PJxBXU-h@k0Kvlx;joI(6V=%2s z6nNkyCJ-*C=cG~G`6P74yp>D7Z1iG%z~H|1cigFPwyz1b-6a%j(6_0yKL zILm2%VVYb$oBQ6{g2(YS9!EIjc!k&N32)msh3jgM_X5XczbbvTvK{+3xEoIVQK%6R zzQI6PW+G>k(%pkivv$8eZ1u}t^{__W2PF;(yY+JycMCFzw!Gqfux<156p)LVk6+Mo zE&#D0;8X^XPGRuzb^y@|8lOG1)O3^Aul3r|H%n+~d0&V5!M?wKdhF5r9xcdUJ)LJZ z|HG}_^6Cpsey-C$mGEp!S^LUATgv~Rv(TMia5Kp~yhp=Cr}yV4hLnGQQ-fj}xMWYy zNo-Men0>AIW(I$`%fsub&sHgQEu8wMsl-Sm@Z@CGQ^r@d!n>3_9s;z9L3>ws>I@Td4_<6 z@j9)Ui?4kKDPsEdp#iKIXdl$A4$HP`T{-dVkW;eh%>V4yv_&1fHD%7JgiolSyQ%re z$y?bEoKpn23$Cd4DeleT`0({a2j2wt4@G-a)l}2|Zf?}z02vE1^VB!iux`;V#bW83 zh2k&&GkSa7N!jhT?83c68vc7)y{0lSaPMGX)@oy5F0BMAM+p~@ekfpu(!5ZbDTMn8 zm`T`turekyyLu1Ee`Sh^Q@Ftw3gpD z@^S~M0RpPn=^6sgx(sT6s{WO!mzrs<{i6r^!lIIPcP2e;@bC0VVm$Jh?Uf_ zGtwynY}~{&hxb$d?Wo%mc_23M-)IgGMPE`E&rdPi9{@v5}Aq5?|316r$jNSJDYG=xS zAONyq@y-b3{)5Va(hoDR+;|D)6O+dn*w=40f#x${USnW|=>^d+OHi3`72xy==Yi}7 z0jT}JGFKcb#|SFRpll-DwB-Vg-2`$wEW8Gr+b9VyP+3WhI0T0YQoRX|zN)w43$Oq4 z5#MxnefnNug$o`3!&`M1n@6ZDx4j#wsB{k!$Ba7AGzu?+kkTkG4mK<xutBrnzN##*DSFIY~mRl8U zd-x$meexsmW4E_Y^?Lf^rY_GTpEasm59I%ed$b^b^>m)u z{13Nw%d0Om`MFO2RKl|@W$i2fY$^YL&O!ObM|@E#2lo!+0H7*hWIO$~}^;F3K( zC$UA@VfMA+n;HD&E)TD#K3k>KwQ%a2rV=BOz>||zPZ?j;3hz?#c+4LCcpJn`3=D+g z3aE|=iWwSmzy9HNw<_;X_C2(ER_qU>chRigw;pjV*E2|bwf=h&!;EPSz%Y0TR1b;34fTlGGUd@shKqs6=8b7 z<^$vS_q`vk2iMj&{bCHi{!U)Lwr0D~ua67XWhfO?Y$~37bJ^FaoIh5#7g{lw^QaHJtl{$Tt@;viS zo-~~xYzS16!XO}ant?&%ERYRzGe|2iZJzalig6Yc7g!k^o0x+%K*iv6ihtl!rt&zx zW7VEYJMLZeOqm~W_`aV-h}AxcDWCT>`vMg*1%w6#__%_!KtTGbYsnR}_)2@X{>s;z z9L3>ws>I@Td4_<6@j9)Ui?4kKsbWfsf~saGTYXs?_VmVkrk18@i5*%&dcIoX%ImK`S@tM1`|*As%ZCQJi@QK^!SvvR zMPIb;A;&szaf#DDyDt04-e4>XElofDb-^<0*{Y6EOH=*>0gw#~6GkBSA5;z$w#>jZ z@CwQ&CY%}A*KfH14eK*NeXKCOAR1-~Dif{(9G7q&$ZimT+7C=~vQRljP~L>HiFH#B zjok#xSD^43Y;L0@yg>Pd8gU2?6Qp_o9DUk1j|pD`-nFmYZ{_~J(TzZBUq3GkeKjL!f2Z8}i>1|Y_8BZdG-4O00+g!vU)E~|pdQDV)9Ih_Fj DrSPoa diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410284 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410284 deleted file mode 100644 index 96ae96bfd67907fda52328f4baf8ff52d32ef2a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1476 zcmZQzfPjLa{I!SgsP2()U}|w=m=&x2C+Ykh$E~Gj)o*$E7qfZ;RSC0tKEK2J?q2Mi zVzs$HzUNg z`xNu9Z=SyVEq=~KyX3+FYd+omEwi`tHa0y_ttiu5uk`+TVcqv&gGIhfPOa9fCi9)) ztj%g#c-(EW#xB49pzJ+=?(xU-{GMX>qG@~S)XZFKD^U z0kI(9R0fbvVes*G0MQB>pFOnHbd%Sw_1e)lOK53%Ux)d@zQ2BY?9uxkEy!Ozoo6=x z!>!%&>I+SNuG2r2@N7$2`^rCC%Kx9U(4Aj!Gs!%>N5e#?_va^ulz)FygJK%EWKYjY zY*BWYeXaOr27kHB!|SQfRw;EYocgAz#7HFYV^Ph1rSdI>liOLT(?==KGwvhJMQ8nh6iAG-pt!)w*x1C(5+s382UefrANZ81JdW>JwWrdKdsjVE<_8?U z?`IKWwNGNo=Y7q-K=n)kp+NyYu3)`jBK_30L%_m# zoz~37*FJ+3F|Awb09FjN59(Hjd@+I2PhWhlZu$PX`rH3VrT(kZJHmWy4!wT&HC=!9 ztI2H(r`Ddm<`!#X{PolSVs-alDNG9-xvhD>TUW=%7mM=(&12j@fBJ{wU+SlsnA%LI z?{o2Z`Fs7TW%>_-CVi_HwyNg;54AJpKM;V_!`uMm{)4hXVap6mJFlU9V#1k$ef^dk zXjq>G>SKlJ1<^1|P?>NQ;JAeIKz4%w)P7*TQ-aDdg3>dTO{|+ZXzV7C+hO4~*xW`* Uc!BZ@HR2E)CP-x`Ec(DS0IENq0RR91 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410285 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410285 deleted file mode 100644 index d63e8309f7a8e293a059a1edf1d467063e00a30e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 zcmZQzfPhs^`%|)63pDc0oF$)VO|r?oo4U$iHjo zm*k(c6=YM=qBA-W8yOfu^wwB`O}lF~{H`9ba$ovz>x7g1;mx7$GDiZc_cgIxvgrmY zaX85xD4-_Bv#&WScbCd@+ZKCS%@8gf^Ce3sg%t3Ys3TfmQZMe-+PJ5MJvh_<}teXwow@)VGZnU7!4as{(M zJO+kS89*Y1!N=PHL@Q`~_Rvz(O$NAG*IAb<6Ap4t2l zw|2{`FEshNPXAQGvn^%qEB|aM|9{RxcYeXmB=hhd4HKQ-pPv{~{{2l2ifQ1IJv}F} zMcHBYwc?u@{N*kWuctm+rPQ@>>YJt#Bay(9lT}X{U)2ilQu27r9{qS5&<$WfD6W8t zn4p-!@U@!pZHd)aj#?=b3l%r0E1u>cDi0f8bN5@;JU@)t*W_?p^gvnICZYzMn;i z)jo+SpZ7KU0<|y&ga!rpxI#38$n;a!k}GEMmG*A^m9IBBio@+xiN)*k3;_${by_nQ zU;7MF!;};SqCkKV>Q;vy_ms6kzGfS&O3Q-puFt-;$*ldp!=on$B%jL^?U^@K`NaI( zeG_$MTeAc8c0Rmz-a>=l``z+SoD-dscV66}RmBN33lugC1l`Qowg71DRtBc;bwK4X z|AMrF(mBW{EO-2z#Y_(P-FtHJqNHAxbdF51ifzlsO!rH>YP{SOW;g)Vfb zZ7-L<39!`+=d4R+++nY2du;MEtEFp>&k%TW{{FIz8$k1z978-^f`AMdAR;U!ifV4b zlruu(#NpGT=#AS~%OBNQdds8R_Za`@ aKTIo)hIdflKdc-xEy))7aZ{G7uJ9^FX zg7CtyhspNFe|J1vTl@3)rE9CcKLm&6S)siW%H0nqSQq=by|UFU+{vN1t1C&Qe(mcJ zfnR@OA44ro`40p@HY^+&f!u#kIZ%8s1M}eH_@v72D|8WdiG&25x~7pUx^MjV2}1gRbZ zM_;DBU-9#ak2bR!-q`S(>s#@S)05{Oy?$}3^|9Aq`ONL@p>d2YjsAkl!P4jxD4%fo z!N4G<(b)q`e+Yvsbj&>;Kc$Dya34ufyDUN%~`UKEukXKX}s*RDQn5S9t7~Td|a9 z_rH@Xg0F*YN?LTr2x21xBZ$6QlzB5L;Jaro`|L+AOohze|9^3Ljvm|o)f=7U#s8$s z0F^j=KEO0x^LL7QU0tmU->rrxp+TQ_8_HK--h46AERNNvm{;)6-0l$3tb-h~ovY5g zTxz7(E-|P4h0gT%-O3ARxH0B?hNTkLA|3CA5NiyMW1K31??%EqG|)5jp%@{aexw#~~^KrUuJenHDk z2gHJaQyD-yg~7+$0YockeD=^%(@kE#)@w)KETN_4eI4cp`~Ldru}ANFv><==be`G# z54U#9t1mS9xlaF7!m}-9?JNImDgS@YLU(?_%_Q^i9t{(n-k+ZsQvUr-4T@>tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!GW8B+WMpE8xl@g1x7RN8Uxs%OglfW!CwEJCdINlf{?ui2M@v26hZ1LIZ(rtkGY zJ>Yl)(qI6LPj4WD<&K}Tn8^XZdrvN2l+>$|&XFlrv2FR7>3(TfjhCCk3Y#WTS=U*+{4uXF+j+m9epjDKxXd)DatgOaY-m0Y0uk)1ZKeaA9DWF|7fr zoDu3)hbuM(u6F&^()VlYZ}h)by0=n$$E)`KO_n!XW=+5Ru(|5T3F}2WvRIZHy*a#2 zVezN5oJd6_z318bt4~`jSX;XUWE|7m|2y|BsAGB&70vYJKmQD^|A8X^7kF=PjaV@E zz6Em_Ff70ziL_H7L9Wo7*S}FHqS-jW`5{ z2~s@-j=rWROFCQrv?{QrE%+F^{M$csiD~vaum3Pte|0|;s=x!TyMPL@rO|)T_{T`2 zM3e;#?CUo#ftCm7f#$G6%>q-jNTWo$$$`dh!kR`0iQ7=pD2Z+YmFd)oL#$~OmNo!Y Cl#wg| diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410287 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410287 deleted file mode 100644 index b4b099a2e37601e07375229bebfa8a90d1465c61..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 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 CbB{a# diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410290 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410290 deleted file mode 100644 index 57f569dcdec136e2ad18c23dfef6c7f0f6b6c2b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 zcmZQzfPn5*L5KXWFy7pvyI#q{?%aHrCegEhu3ngITHR+ApSyiEP?fMs-(D&*- zKqU@aZJ&1+#9cnG?Kbsz$iwBHk1I8fM+U6(3cMupaQ;b-ll@1k4yvuY!KpxVQyD-yg~7+$0YockeD=^%(@kE#)@w)KETN_4eI4cp`~Ldru}ANFv><==be`G# z54U#9t1mS9xlaF7!m}-9?JNImDgS@YLU(?_%_Q^i9t{(n-k+ZsQvUr-4T@>tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!GW8B+WMpE8xl@g1x7RN8Uxs%OglfW!CwEJCdINlf{?ui2M@v26hZ1LIZ(rti%_ zJ>Yl)(qI6L&jcWYW$&D~a+~&hEqOSPXQsYM$`{uoY+vr1PJgsXC#PilM3YpY8jwD) zUV`>P)xEU6T>d7&Rx_NlE}3zMy{7H4$%Q9{N&0}&5@$?GcW&Wg8c_fV>`BTZ@(vHu7H^Gq2LX1F>epukNVXn%NO9P!qQ#EaCqUSDzOL8 zK9?M7{OrG<2WTKDJQ)mMJ2KDMpm=5)i)!{Om2WAW+|Ej!K1z9>c_&YrP7pQ(DoJ4w z5IfDlpm7DrMhnZcc~CLVg5m-zV`F0z1E2s@3{DdfeoO(OK>cN)>ihSRM@oLpGzTLp69=u@l^cOzXlExiY zJ12`SPu?}_`0aPw`1q9fnWS%K2b#z9D`sWuEY>%+yK3j%d$ax`XXMrQapv6%R?OL0 zcsBGxdMwn=l>a~gWW&OQ5y<@ql>>z>GcX^1gz||AX9o85n?#^teHo~a6{Z(N!z@8% z!c~Cd63zqJ4FXX6foa|eD#r*a8=!0=-L!E7jok!tJ1o2go7*S}FHnA=MjV2}1gRbZ zN8fY}qtf09_k!{T8;{PIbn5W>>7VbnxXPKqCA=WesOB(=Z Ce2|I& diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410291 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410291 deleted file mode 100644 index f0233c2ee231eab584649e65b140ea27232060f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3772 zcmZQzfPlRpHwrp)a-MD8vSQk76^UOfQd(b}6FHW7sn7z zTB7;cRW*=JNsG?-Kx|}S1ko#0&Pwc=Tgv9EIV(DP%@XUwtMrXBEktd5^k;89o%_KU zsKmj1g`4e^XsvX)^*JUy=0{VVrk|GkcwY2@^I{&I9Sl=VSHF6Yx{|S1=jF_dd!7Hp zj(q97mUif}@zk%L;{Ok{c(8rCayWSR$3GE;D-4gAe|=`UkvFcY@3Lrm?7H9FyUPB~ z-Dsn3@h@ajbPa!7&gWbERK4tqLb(|uPcl7yvgJcq;ZFw9me0HowryUX0&+3)@e5ks zOF%3LIF$jUQy6@_9YC~##%B*LHQnU(YrS^#%@SH#-q&G%u-Pv@D< z|8Q%!y!t|upX>BbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}qtBOgDY4_e3I=Td(_&L^{**rAXVh!1 z{{CqnJJbyhUtE_}%y=mKMZzWH;x!k=tMd-M?SD1z|Bswf#`1*48~Xa0<{xCSyQlS_ zSejXCQn{LcMCaNKy&F0nZd+%z-{2<5ui)@Y@eh2;R3687tlCp)$GxkbDf0sk-}kc! zvDzmw<@3H~Uk1ju1;C)$%E0u!1*iul{DAo(4JgL4cg|b6P5Zr;JerIa0a646E@wz-iz`}T)*38A%K7-UT z8tTH7GlKmGj1%!Y-Z#Y-CfV`Mk3O@bAnoeo&%OccAG;P-*_>uGx{%$@t`W(2D)nC@!!v1_Dcn0+>2t!;dK- zG$_Ew6`~nL5)&>AGp02_budER>cI7K&m=jn1k7oa6pSRN~D{dXzV7eX>^dd4JD0| z=q6D8NR2qenntfq^E|-BXp#Nzn*X~cC#OW6ZfCe)&$4%B;!DA5*Q>g>p$P}v$^){I zk`FvdLDOjNHJAv&wi8gH)xP#c(Du_Lm_8VdWC;=zCJU((;XHUb3b8+FQ4q`>C}B>d zo9t-pCah_6khqPK@S2PiA7Ca@#33=^szBj@3_$H}P+f?gMnQT(a-e$pB}fSf5Nu1Y zyTvyn=$0r@=>}kuodDK^L|}0cir)#FfAhQl?N6kb5BD3$8AP}7k=g-B&c~VwVe$aL C$GHIj diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410292 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410292 deleted file mode 100644 index b7e3e9ee0c68dcf807a403fa817da3f70b823878..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2708 zcmZQzfPhnbl+*S{$RAT_`V;rRbE3?9`f%%nllvfh;`>(d%Zhd49`OSVk2V?03*UBJ%wm{eS)1McbHOWt z*?I>a|4zHiUB54@?0e|axqBJ^)*O6&XsykuYtaEG>yA!&b_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgJZfW+>2@*cu!Bf7t>_c4xLPrK;8!6l1!Y9|*-t&p7ke?`RpwUknUkCm9$N7XjJe zcmvX40F2LUC=({m3*<9~dP77xRA209kd#f>Dl8+=$XDj$AY^BuY-@Dix93Lh-aF>H zKvnx(UWvMcR1@J2#sF8aQie00LTNUl6LbG;jbd0`sQx<$-V(;d&%oHW0GK8}gZu?j4+Y3<1`qZfsV_5gGm;N&^w?wISQ~Tn z_60f7O&dg$7RyYRjCldlBYQR#t`}@BFt2$$U8uNbfp6Vb>npu-%!_aMolbLLx$*Sp zb~ooXD@m)1%56SwtCulU2A_~r-~S=;>5ux>=ZhvetO#+Jx6QgcgA-^VQ}K`Wuj{qb zHJ*RG#-^=sc*bVt_{_kL7fp{^zuvjNaNcjIr78b`0LX^9n-|Fa2bBYb12fQ%V0VJV zh)5ga9+~Awpy_lWSU*T36u>M2a*>!YSxC6Uc_6z%0BS!ljSE5L7(rzLlufLg5@_ru zP*}mjYp}VElJHst^cN%^paG5)aY#(4BsA~9c`&`u_(H08z)ChszMWBXulGYnS!-pyq%}d>|W_eV{Z7%76X&Rw3X^tdL?)Au~*`M-0{`+wj2f8YQ8|9=hyQKdMA!1q#2 zA~l>Sa4$oPo*J8Y`E1Rc)25m5q4s@-a5eF!oZ-M5eis zVC1mMSxeo4OnJT|<+m`&btj%F98V{|;k^7~9k=nXo8G!e6+G=DrJBN?-16^ip?ZW+ za7&bJ7OgxPxX?l&3yVE>M(0-1DpemXwC>SW*_WF9M%4fWBiSn{N2qcs2wL5Qx9c_7 zHyov<`2y{4_zR?4XI{5wt+SD~&~qJy_H}9>A6YiOE9|e-Bl(S7Q)R0j+%_V37}AsG zjl3UOS?VEYBe-^7QApwTkvFZn=f{tBHPu=#Y+3U26M<2KvR>_fvQ*Ts#g(Lw44K_} z8T&Y3~*b*-nU_mDvdbMdO+r87`T;^A2U&0q3nL4 z#FUhnC0G!gcto>0acc8QPVDt3xx0!_@MiNrz7#Jhm#02)epRDue|ga1-`aO1MA#O!43piyrvt|yZ1nhnXMd4QTwdC6M1ZQW zRYS`1Mm4gceVmL*FDJIQg31YkX3G`8EdUoAjE_qnveisZ=`th=x!NXmZW7{=IpdyB zShB-_+;b+zyas~g1R$Z!I0&^R7r>Fc!Tn$X`Sb@3{EQ2~2d}+aT}6X-4;m_#qI*Ah z_!nITd+tzo6iH7(w>G6;yWm`1hCtul?n2yO0LP|pYvEuG_n?V)W4rs_ti^!|mnL_u zOmXBgZVb>G3dRX&shwBMJl#G9!$k2v9iqWeRGtu~53jwFBjPnWCnf2xFdgf+O}r!^}wM%-c$|Fg0ztuqCu&?rTjioI37q$OgKrN z6dymF`_11?DpmADoN78-CD5f8(Qc=gp7_z}8H9?-1@q!Hz%$2#S%+LF)5UugweN)4 zk%Kioz0sWl#KksIoYK*ecD*9&7HGoU*(OI1!7UIJVi(N!=oKLctb^Snyc8=*Pmh-Kj`qv?BvDW_j!iYANJ%tdLmlcq(odu7@A0qoxnMDkeelc-~+ah zF(eeG9We+;Q_S}smqk^obex~sKiPIz?oz11RA7Dn{xcB20R~zm9S-m*uzzsPB=B?O zoj^#NuacIUNyN%C2*tSWtZCb8&?-pOE?}h zRdI+hVDnw#g;m#_(tCaxKYUyB37>L{PmSg=Y+@I#tvfH^MEH&l4jKnc*6VSP)whCl zqjVEf!9;SxWEDc>G_e0`2%)0^Cb4BABMMe3HSveV3fH-Hbtj=OllW6|BE@|r4Vw=r6B4?} z<7=-g1(kC6L}%Q#c3cSTA+>X0$h_=|MnFf?U3AN)`0&8n^rpr7f?Hkgmx73 zxLajJFTV7Y5euet~t8EUAP&&yruS5%??E-lvd z%vSaKYXL)y+M!H@K2?k$xMZKqyu$88IF>4pE27|q2fdZY-#P0|9ndOEYD-;{E7VLz zH3eI`)tA+*6A<1x6#eo_s1BsJlpF9{5O-={zq*Wt&Od~uoqkmduop^0jz3nWa25|_ zH$WS&wgLbP97o5f2Lf>BqU{@ua}~J%K(o#F1)aV= zj?y`>a`rmywNRgSzS|G_!FwA+nD{fPjMrb9gNT2y7U|NE)9QjHPM(vo-kYr=QJ z?Q7x%pV8+dho7z^NGd5(A-@L^eT_HQ1{HU#I$~+_C+WF=?fRN71y$p2Y_}gZ->mE> zeh+AK1Df^w4FI)CWMSGj+;Mt8ddoC1nN<2)>N%Hj$2jv){k!E`chcTXi#cnY+LXRA zry1wycf##!;st+8OcSQWF{up5m)4n2=P2BlzSklDPGAeOe$Supcx&1D3Jsta!HS&( z_hFV92u&M13-)_BJ$dG0f7%|z@_&Xo>_Le_V=J-6!;dn`wR){vYu{~toPW$pZMaNd z)~du_dl>%L1%#zKen`ba(5&B*0H{3>_8Qa-{5?5eb&U82b&SjfV0T(>SmSh%_ZxGX tv5vnJZeJ6x|D%rSd1a-J=UQje#?C?=*Iyrz`R{ei>OYS;)G@vG{sl%V5&r-H diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410294 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410294 deleted file mode 100644 index 7bf15567d2abab732618ef533fe74388433f8d64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3920 zcmZQzfPlNM>hrd{a3wk3k-l{*GH?FubrIgHRy^WT;}5EO=@BCXR3*H6@*Lie(sEN8 zR|s61VZm}Q&EaHb{z07!&88|>l}`A4)%#o5yQ_J=yqc?@z;e|BL&a`a=aoWVPBcp` zHOY9K^BrVU(xNlb5E~g7LG%ihvl4sema_S3&Wes+v&8!FDt)6&3sKu1{n=Yj=YB8- zDsf-Pv@D< z|8Q%!y!t|upX>BbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}N%EpOf;moCA1rC}Im*DGF2Eq{m%+do zwh*Ws9B&|fAOMWd5+DT<<0vRDurf3;Fop7g6h!Sy+sox|0&F$IIqQ-cci3y%9-I8k zYU!HeGX$QTzrQTw22dT7V~B5L5J(3Uq@TK$TrrEUw0G;Te7(t09B!vdEMAvq2v``e z)0(;X+Gmh5i2|txsB%V#I~g2ar!Rgbxv$J2^XQR%o}G!6%NOUZ)4I=Re}=tJnIePnooam+vqDhNorc1`WU|?)p08AI4bO2Tla|e(HhYvyh3=C`_wISYyV66$i zrpZ3mvN}^AdbQjn9EIRfw(dV~8fZ>5`&beg~7dLj><%L)tTzzemLXFm}RRJoJ`yad6BhH|9%Ck zM~;7FHbaY~C+DVrN2fYjHfUV$xn0EAH+N|`>!(jG(eofb53w85n`wUr;tE9GHP|3i2Zu5Y872;xfKQEYQ5M0H}!vq7y>GECKS6 zm~a)y=>{YS%8v{%`+@l?49o}V1(rWhHW7Ih^dd4JD0|=qB_y zAvX@u(N4as2P%8vWeE}X0@F1-4bd)4D036C|ELvD z3~4WBP4D+|N!HiLkz(OBHgTf1?t|M6g zGcbsIl)Zr0PsoOW*eD)_NTQ^1;>M-o6{lHoR_JVT6|v{pvL;vK_YBmpEQ$!-FrTX@+*bUPJE N58Or|1Diu&@&I;3rf&cM diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410295 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410295 deleted file mode 100644 index c2a15d1d09c22c35f5b5f79320b98a73e13c3a06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4736 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 P{-Q=4qL(A^NCzvn*jgQ1Wpeo_T#;aGHbCzxN zm+8C6sJKe~7~6`D7s>)F-saWbv^+j@OYYw4Z4K+%x3F0*H{AEi<+6ouZ0r3==?qt2 z{m|-2l@9{hl(gtf7Q{vdMi9M1<*dY>xutBrnzN##*DSFU-c~e+V*Bo z1@B-cth){I^hSaSIJxYY9(_zs_}B+EdmTW_xYdsUr-cEkAi5Y}>p%1>|Dp;}`UP zF9ES2;8X^XPGRuzb^y@|8lOG1)O3^Aul3r|H%n+~d0&V5!M?wKdhF5r9xcdUJ)LJZ z|HG}_^6Cpsey-C$mGEp!S^LUATgv~Rv(TMia5Kp~yhp=Cr}yV4hLnGQQ-fj}xMWYy zNo-Men0>AIW(I$`%fsub&sHgQEu8wMsl-Sm@Z@CGQ^r@d!n>3_9N)Wst3mz z)DC1eL#B;$59`d8FN<`}Em4Yan|Y>n+R4{y2Nf#QyidL`Nv;IxVfyu<0Yn1nZHY@dud5okYS!tRCbP|tu2~5h89Ur&Q1T0PIah8KnD!jl;q-(UfP=>w=r_G~HxvL3KTD1pTiMo^xDsUgbz)AtfcFdvq-LH?kn zJ(TzZBUq3GkeIMgf~0de4-`ir0QDbQxeAh_#P1mPBMBfe!7cz1;5-QD;d2{_@ga5L z?E`4MW7vx%fW(Bmf><}f!w{sC=yD9nA8;Fi3~UbBx5@VI-+14ZJdL@hE^Ou0pHUkV zq8nS$rFCz1?DvI&AHn)D^CYrSusjJWzrcWCc?VPlE^kF!;Ci51!4$ILP;r#BOqBUQ zGeL1ftoc~;Bn|AL#2*;Jf+T>%goh-tX$+(n7KiY9l*)Aq#8Dd;?a@05W+J;67A9aZ OD%%UG%dp!E4=4a>9qqLM diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410298 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410298 deleted file mode 100644 index 717df905de6b899430dac5a3b5ff350bdf98c65f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4080 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410300 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410300 deleted file mode 100644 index e8c2d1b8420721e16b6ae891e05f4c66d44a7891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4148 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 S=zboOKj1M0WMGRpm^=V7RGQ8J diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410303 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410303 deleted file mode 100644 index 4e4b63d9f24353c9cf47315a6ef0178b47812cb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6076 zcmd5=3pkY98ve&+qawNF5*5XvV!9e;(;ksqXk3OKHb)sH6-utTgwjFwsYFhxEoDeZ zM^n;6ITejdxoo$zCt{SQX=`l`up1$W{eQW*STHpJ9-}|q%{y`9) zWLJpo;_TY|i{Ny<(|F^H-q75OOQN5@vmc=kB$sa=8haDj7!*;&icGU1U$;=^98U7}(uAJ2 zW!A*=JR&66vfZTreJeuCw&@PlJgbv^j5F6cmSL`PkA9#mMx?vIT-6yKY)Zk`Jqo=0zt!H{x5&fh`i;g{fYf!75TIfRMG`AWHuQ)>C=5qF4 znMa|DpS)V3P||oe+OEmv?CsTocHtYfa(=z_Dru!>`l7af&iy{aabKO}Pme<0jqe_c z8{D#gU{K{@or$)m&q^)RT?*$C5&1*ok{#EJvY8OEaAh4?R0L`~sqzLb6S3YzgKbYf zS5yC{sTJcxdf?5P%d3mFcRK{IZoCaQFniiVDYrW{=gizrcH*MHonJd#K(6xWxfXQf z(&)9|@rU|4Kl`_Bqc|VcTDu}?_!YwZFy>|d

~)#+OgEuo!h4rue98*JLy;?;KW6`GIXh0WM%9|8WzGre7F}YlUDtV-5M-)a0XtFfCj{;NwT>Tla~Nl3D2bVT z_a;!|`#QBB6Jk4L+!mzO{9$`P2$+D#oj3@hb^+*U-QYYZpq|-04Ih^TeG+36Z&X~P zulS&nss~$EMLJq4$eJdzUVn+v>ZdkGTa!wkP;`J*ndu98b7(C94ibGMYKqiY%4|23 zKfY&_?Sfq1w?VsJC3mZ5=pCN~$G#(m8~!oG^NwPIF-`~1w0-b%M9Yb=Oy85&(9@!L zkXB^o9PUm(rJ2AwOAozuZI5vI$}$VG&Le|7QR3^m@76**>dE6x<5!{x}&BlDb|Z;GDSqJm1Quz*4Tg)8H{r6)MZE z{P>{Rqm-PAvxRaS$l87LJnqffL&oD}ZnpbPDA--9;((=kF}KN*`7{0QQ(JvUYMJ86 z*JZIbXuJrCjR+0KLH`&K*aH4#f=1+tt;zhgcWk-c_4P`+VGDMv1S~Z=G_cdWp(NbO zY;hV5*x>n@(jVW)bEC%Ke!7vivqYpPsrUzNql)AnYF1ulnsoQ0r!4PQu%?i)qot`m zP%zn1)$AE^S}HJ!J>sXE>>_SfwO{}DU~g&tH3iH5b)oq+uv6R@{unbSq49xSF4FH~ zD#x)@b*x?s9eHqGEB^Iny;8lsx!&bwa~Rsr!`ue~#`4z5g6Em7!Kuc84 zvuoK`b~otNNPz`W?!>ZBT$n4Lpx86!cfC=!^gLatqq)i9YVpe9fmdA`a}xR783Fdf z7zohfxtVhQN8Gu{PRY2;a#-BZ>t$WxyQ8J$gf_*)$EwQTr;cVY77uYv;0}rb#H%bS zW9$@@*BN|Ka*LqIX$ z5acgmLe2%mnUW;3%9+e1@(iK)&!hl>p}=h66hviFo1Oi|-`@_=UX2I5cxP`7%rs za!&}BpkgWc?7Q~KUh-b-*(Hm()tpZ30K9iRr>us^O#@6@6k=Ep;O=%BVwr-mLDdUw*ZT zCd;U{j$d}ok~5TYJIb%OAonqhvxoq{Lm;ZPUI;kr@HsdGfiej(C*)7C^_l6@SbtLP z%z&RSiQ|*B5C#Y;o=F%JQLyvoV;;b{#AoPQ0>qBrc?9?!3Bxhvoksw_fIE0?KZ%<# eKu|IFpWWX+%?V+D`#&&E@J;9t)M;bFC;S(-vdDx0 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410304 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410304 deleted file mode 100644 index 1c8773292b757f2661a6bf78c7f0511d767c5e40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6376 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410306 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410306 deleted file mode 100644 index 94cfc57359a85e1fc2c91ac11e94f1dd98a150b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6692 zcmd5=3piC-8{P*;m4!mPE=-g~w*zwIyo(|(?F*4k@*-}>I~{l0bC3qgdB zMCmk{zLa$Z(<|d`^CZplwPzR)Fp-MikC`-I?%U@i0i@&`m(=#JE_q|y@yj7W&B|q) zF9Zt84vUw%^eSh&=f5gu6?8sI@5q0*xZ_*C@*O^FR@3ejdG)Q$XE|X8=hIA;T%e^* z$))i^iwF&tKdY4~-1sp-{40%w_3JODnBG3GtMAE}W*)73GW)?cfdLRvfYZi9(ze8@#bDncU@vqq1qPfz5H^Cne>vjIJrg(?{4~*WL}Yr zfr?t70^K>(r2YO}`84`M*T|x)8n)hx%wDf-^@^;JTl--3dD~D~!{aj*w+gh9id&i! z3@YOElsGS*GrpT^$ZUGewM?)=rbURzyvWH+V?o5C_a5m=OT(J*;dz0Qg;=j)!m=s7 zZayP-#cHR)#DLt=3;LPv4Qu^UuXP14S;=oQF1C-8J~^pA`v;W;Nrt_bba}2#S%Le` zy~_$3Drab)_O01u>>RCbsCBUS4Z<26aC2}8ov8F6abx&g=E-Wm8jndqE9#%PHJw*I zkQCb<=C421o_lN_&!9@v`GD$|FDI;jnIpu6Afv?!$kD-11j+|D#kh$xxOKPlXhY5QYtBVDOcMe~pBo*YNrxc#DFJk*!${G}4B z!ecXXqqj+TW(jf?H(pMORJ8I-x+3Q{`}cdD2rcpqGA;a1ATNetfCb^#sQL&3V^4Ej zqmQb4nk|o}bI!eDYn7*{e!Y@Y8gYW#HotiGF84Lu7Q@ZEP$BSVn!tlqXlEj@;a6P3rX5FCuEk09behu}cskeK8I`ormGtFBkGGi7-5wazh^s|q`_7o;V3Z&Ee{ zvNOI6Y{ASRG!z5y_o-=1{LzRl|4FrQF;3Arxp7aeRqeypsFcUgncI2x3L1)hmYEfTe}MD<#H1M?!)N;EP%98!1ISwJ39{487hMv$nTGk@V@)PMUAz}Rx#1x{)#E7` zQ^dm2%Ekdy@MjCJdh^Z%*?@!DecN@8t&>>E^JlaLc}!*)T+-y6t?qjH@b3cdz%TU6ZimOwW@DX9kK@9Y_J#sgBUc+`6 zUj(-ga{d_l4t2rahSe!zO20qOm>?dUug?wJ$M6N`%cqDT$_eQlg@#Yr{^S=E95ZI9 zx0LWU@|U^BC?DM5sp-AAymiXdixGp@uo!QVc_{*SJ$`@uLe z*jQ*m4D<!udku0UiEKuno)6F=B%I_`*Oxof}SMqZBkEoW5C7wQ{vo_j~P&lIjLG)ZsoKdKr)37}R zo-J_uLZd{y!w2vNDmZ36>QKPWo5UWA>yr$Ss(7#PY(u;eYq-!p;5G#78y0VBnA)?( z8Pf;n$7h1=WB7vK48(kg{F4Gls$!9OPZqS|`|$ho1M0%P0iF?v@yE#5_+k4vOhTVA zN=PK3RqVS6>mAN5$_MPh?330Lz*BfX=t0Mzz|&aP0TD;31_Zg9d_(6BG)@jNs0*?D zzwDCe0txc>`4$C+VL|hS0tZ0nldp+LrQ`C*Ds}A{+}GlLr@BJ78!PBU`{!*twP2Dt zGW)){s}SgjH66Vp0Da)QusIQvfquaJ$6hJiOW@y?BppH-RECi!?7-uPzKweCf#ah- zKJ)?i1C0wbG!Aw?#*Y!SkQzu;lp^>?_<^1o|LBrOtG5S8jKB<9J#gI_PM)*Jh z4_sS%a0{c|V@anL#0*$9!te4c;5P!}hz2M_T2CpApJsWpEM^SjBUggiJ&&~yzq*~0 zv8U8breCpg=bi&gzaKo1uW4~WMJ^rljfIssM0lrzKX?w~eF%j+Aw;Q+m59w>s7L6+ zK}j#9DsJu{a}1RQ>;4D7S1Dp*j58+470wrtXP*hSVYxO&OwgBMu_C>Ys-wmb<%G0% zLtXM3f{sN28?lE|xNpQk;rEVYyu;Qf3U*;$<2f{boRHRp{{a(`chGT?v!p6c$v@7u J_v1t;`~{ckG!Os) diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410307 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410307 deleted file mode 100644 index 28c6d05d2a6b118fd8059eea35a3a4294ee82398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5688 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 s4b%7 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410309 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410309 deleted file mode 100644 index 884a3c530b065a5c2881d1302381aaede943f0c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2428 zcmZQzfB@xnl8Mh);<-|GzurAbV$w9}`yBk$g-_?y=-gXp{N&?Ppeo_Np3jRX?Qh&&lv_`g>?ZtK@vEEW6g zALDT?hLbiRo01ltSpl(;fe}PsEy}!^6!6_Mmwoo57p6jH@BhEJJV%dh|LToS^5TEe zWq?W?7M<ITvarwKEm9Oc&Z+ZLextackCug>#tyor#^Uzq5~d zcR=>ONgIq5p7^*=kvWC2c-O85qd7&Rx_NlE}3zMy{7H4$%Q9{N)iXJU_(lf73-Se%;GEU-TEtEZ*mle+o=+Z*X0=k7RKweW-h+= z8KhLAK&k;m0|6t%oeT~ececFilQ+!&E4JwEoA?(y|HZSOiHZJh;U1T@;i>4xyanCI zSGqdqPkXuRr^u#Iu4fV5%XsES?VGelrm-g5#Ge^x7ARa83|~7k&)A@NW*UoX_A8Zd zDV*HSN}WDRd7gPEPnu2;HUuh3VGs~I&A_1X5XeRgld~6~Vw|8bF*Y_fF#rlc#o%;` zf8bN5@;JU@)t*W_?p^gvnICZYzMn;i)jo+SpZ7KU0u?d^ga!rpxPr7m05RdhB*u3D zs+?we7+u{s8kl7@a%&Btd6xi6v|CSGz$NeW&D2c8&w|rYr2IJw~3$I zFWZZAGE|!pg~v{`ew{`{FUXYP_4!80GoOw=v5 z+B=IGSC9tQS%eAeub?LF@YsD>?`1+^bv!t=U2Ghpv24r<9M)=w%RXW#fIYZS(RJkc*j*U(gq9 z0kI(9R1T0%Ves*G0MXCZ-cz&K>EadoZ%*mXGpmg@r#%TSUbg*fjiuZDXXXb3r}NC_ zf4H?hw{{^UOPW(sY8bAy7#QgMip+1_q5s zKsGquK>9!+Y0=rMKnf(rSx{VHWefzCAPIyzu=*7Lz^6>*aeT+BJ(YIcyXu)TKj83v zKZ_8neG*eX?`!r2s%Hua4GQpa1?vS9>8GwGSIpuo?cMq-UvF|0huf(Vi`V5D0v5*W zv}P{8_8F{b#Lw5c3TF`Dg-{GkA>2>E zOv2`al`)ywfs6;6&lno);tb+&$j)=vlGQrNZhqA1ZwqR!9^ZS5Lwx@{E9Dif<@b%e z+(Bx9fGT#nhIoJtQ~Oi(uS~tvOl$R@O-56ix~!tt|Ga*Ban=^szE=v{gfD>=QOV9o zrwFid6Vn{tPx-f_ZcpTa*uZ~h+LVq<)L%HqqM*|}Ev)c{^Kq!1jF9+Xa5%|i9Cq%d zm%gUrg!F0tpCpP*fSCLsQ6SX-RnG`RoU@#^NpC^%X?-&aFQ^WS!1L3#qd&_`I_C{sX|80X@z~^vaF%*oIvxK zd(X?Sl6TZgepyn&%C52Cv`!||RH6Y4}tpNdO>EuEJ0<0WWWF%k1!69hU7!2{lGX{0hMC}mG3Zh zM3jXfH(AiwO(3_!!fUX(jgs(s1oRg*;t(7rNNovl^ey<#si0-eQ*_cUXNQ)^jJ~2N zxvSKIdXk;QdwH|UT0cSJm{A9sM&ac$QX1vO!G^^JOb-JwW%uIL@0rm0p$=#_C?CNA znQ0enKhWQEp$4JE1#xcrW=mr?VNJV(#BG#>7pM}ZMjT>IyAP~#7%kKDzA&8nsrE!# zIcz4A_5B5ThiB9Uu}-@CsM;PH-`L96Ur;$%8inUC!gUyfxQx%90%$$91ZWNq)GRPX mW*PMgQ6g*ZBR3*&q+Amn!Qt{(c zFl%;FN}7y*5T{Vd{G%EBpR4^%($tQ1ey^Qj_HcsF;@z)ewlCmpFaM$zt(nxayC{0r zonJz+dqFlOEjqIaVj}}1h~642uxWR#hTqi#R_;q5Zk=$FKfF2AUFJwY^}Z&SOE%p= zB@Xt<4?`Yk_|CuK{=~$Ke?_|Z*O;JxkB;n6Tr-c)Hb-Xf`h&51mx&esbhS|o*sy}h zk?V!x3*!s3S)Zqb))nt$V>}(98TEeA_B$(D>b(WGabCV0cS8ATQ~7C==!(r-Qg2Pz zzwrM~zxPjjB(&>psORZuM4#pfdsEbKBbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}41XtQ`eF!X7QEwZvB<7H#v&K?No`y>+%c%3*&WK zGZ$a`3{oahAk_d>&IoZQgG1P>6#^R=_>4LWf6 zwX-cqUca$5TKMNBX(waz^ZhsGS_*A@5_zSfWV^^$W}tbD-6t3yiypbLqsBJ%oew3H`9SPc7x)hZAoVae0J*=QY*4r|1Jex~lutw$Glr2;HwZxO2gcD_s2n3GEkoHvx@pQE8oLSPc35}~Hn&j{ UUZA`}jW`5{2~xQUi#{+70EVfcbN~PV diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410312 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410312 deleted file mode 100644 index c56b241904a673d288dcf37130360093ea2c895e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1472 zcmZQzfPjDDZ#K)W`L%SXZbQnoo6J3(|MoYm{;)k(``KCfGdBY(fvSW*9FUtQWuMWs zK!{T@>*mWHHM@dEx1?7sT@=1OtWoe-{oN$(NAsCXwiVd^xT@t4s5I-Otze|JT-Ow? zkGIwH-YHei;mm zVauWVK-$0n7@rq`43JqI1;qtch9(B4P(DZ=9LFzhFPFawu+Z1OX! zrE8AQ5O{L_{<4f4Ky^%xA-<78ARSPUe(G9s#Vo$k-mSm#^(IGgxScAocwL?$U}3yY zYv$r>pFzqb3ZxpK${8Wj?U|J_uQR&XDM&a{byg!&o?h`c+U+qkMYFZGwcr*`kU0x(v6c} zFn5c5@b=FWvg4Lr(ofA|uTD&a*r_h?9|%C|VQv6&e?i%xaAgLj8+It4h%jalm+_hM z2O7@Hfckh~dOzH!1vnnzJdoWW0JR?&N1LE>jG(j(WfSS9+&46K6Ugnb@EUAx Wqa?gQd4(Er2o4jZauXJPU>X2WT&zU^ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410313 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410313 deleted file mode 100644 index 2f97426227a57e031390eba64f1aeb85fbd68687..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 520 zcmZQzfPnvQ>-cBv-Z>-KfBhe(q?IOD%MbMiZJD?@S1~3zXO*@JP?hk%@Hd-f*Zf+# zQ@0`I+D+!3&VTzGR)5$YtNrY({F$49m7lLnS6&lvcw4Ks;psK%6OMCN8Zd=SX#ebS zp+d>mtL+rXrldt@_Cai9UBFrPPV$F0hq}ug38>!J#B#}| z8>qxVd&bS_M;4ZD(q4D@?NhDEGyZ6rfA71a#`H*JSKR6PIgL$U_MaAKU38XP@Amf2 zKP_TUAN@%Z=F2YMe)dL1PYyJ5N+k;eXwow@)VGZnU7!4 zk6!{}LBOdTAf3YC zna%%jYqz}mLX)5C^iL%`+fvrP^3Rs?|K}`p=NH^eG7s<3FwyD#`H3Or-`~`rm-cBv-Z>-K zfBhe(q?IOD%MbMiZJD?@S1~3zXO*@}#oGfila4QFU1YFzZ-4AbM-8z^2``8h%#~Sh+8KxOKuw{_y5dcbOvr)%%)QF4=Sg zl{l2Qt}0jEeBfu{mG8;S8d!T)YpqZC;)NaxwGq3;GEh zAQl9i$^p_T3_jitAo|(bdukRtUA#j7%_-e^X0_4gv?syE%eH^5v2?rt%=}>Bbe`G# z54U#9t1mS9xlaF7!m}-9?JNImDgS@YLU(?_%_Q^i9t{(n-k+ZsQvUr-4T@>tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zs16kVOd$0I8WUS%ga0pEAj$5`_N7$S`hsFiSMvj*Sm_yO-ufLa11bUfJnSR`gW?h( z8ys&SeINjg&qojzT$~rkXAJd*h;pdD*wG*?!X1nOu3)7MXFP?{Y(yvK{@EJEu)4@e^PDC9?B*u#oLHN#&D#$3SIU1N0I7%ad4b%2P&Oz|nHfY|K=NQfM7WB3WS0Gb#_?jH zCT6HsFa@&&$U$PlRe;kFoCnhjwI7&1I-zompnL>VN2Hr((AZ5Nw?o5g(7BD0@B-yi QD#RfqOpwZKSoDEu09c~O)c^nh diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410315 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410315 deleted file mode 100644 index 166968ec0de3c4931acb5e84ed9f60017018f0ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1728 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 Tp!`COI0T0YQrQWMJ}?ac?kJsL diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410318 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410318 deleted file mode 100644 index d51a3f646882f4ebd9cfbf7d9d26bc1b4acf47a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4892 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 BU?2bh diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410320 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410320 deleted file mode 100644 index dd8d016d948bb5b4c0a5826c237b30541ddcc245..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4884 zcmZQzfPg!x`fhU*HI>%2X@B`6+OjU=t|-getozcplnnV>b2_#IRS7RLIntVvzauBQ z;^9OKfxMIo!$)!!)iN?N;lU7`DT!A6grQ=i*}Wc*6;QatYTW1Uf4 z_;z5h0Nane{p$^9^3xa8=d6E|D?+R zl{l@%%%O!-fKe^|ET$nsrJ zZd7tQJkqh+Um~oac{41xo8hC}?&MS3xfmZp%1>|Dp;}`S` zEkG;?IF$pWQy6@_9YFN6wfEF4cDi_l{+m;}^UP|a&1p}9i{lw^QaHJtl{$Tt@;viSo-~~xYzS16!XO}ant?&% zIgkyGH;_IMNLqA`6G(x?I17pktc;CK%t0D}0HzL1r}zgxWh#&3J67$fwBz1Y&y@KA zhwuAYgjns9nDTjFvoBCRQ$T1?fR8I!FPKO_buGDK7GG)a)?fL0lcPA?PL)`^F3%9K zFkYuMbMdv$AVo|`Q7{dRP`5fLeL7kkvpOnIz@$%S7V9=cg_ovWT~X~muRe)rWOnT; z^X^D<;>Cig@k=M@^FOAmE(m|I%+~Prrd`iwdTm_4sp;cu zW3CSm%0+!Ma~}R!{b*;f5YH`*C}#fVZ?etmVOuOt=Dpset+vTl!DRDuR-k!cKeP)a z-R0s|S!A@YXo=&5aP4pMG93J0KdU`De4{RTedTAcAGj6Q0M$a5Qfa=6O%3i>fGlAU#^!Hs)k!68vx_Uh~EIle(w$}OZa`w3O zcTciiu+_PBzhs%;bW1r_vw1hJe_J8p^0D5S^Ol#JaN5*~-wZRIeX%^p=Hl_|8-PY0Yt`6fg2=iRK$#n2@wsvE$?dF+qu+PLfJ`8%5n(8_F+uG%XHT z@N9X!f9Eu{?Q6Jz4g-fD!F0>mwg4D3TN#+X_X72xgdec1`vVkXx#Q<7W^%yq-jj!vU%fte2pDP&;1QUM_zVV5=Fb$d6c zoMDMwclUQa??R>8_mjnE@9;2q{%@jt5S#CcB%3FqhkxF5gIWqMVS#LvaD>W%;)9t% zH1`ga&p)S#5d7pFp?ga+d(uI_cJ`}{ryXN zpN#bR1M_1p_8soh+&Q~Hfw}yz#ZzUL#SZ)rp!!q(0|Al|j6m)$s2nU^g6d5$Afn6@ z)97qh0=fuP&h`K`@j|tNDI|9yG2tq3r2(-0z%+0dsuCq`h;vihJ{r3T__Z$FeVf(+d2z!Li|CN5+?1?ce4lwO>m<(X+Z9 z8sFH`=s&0&EX?6)l!!Jm1N-__E1>P4mj9;AK0Be#fvMNdSpShTD+Z1jM*W>QadeG~O}nMG`<_lI$jwwhht! QY9xQaZ3Hr~IRqvT0Le9fVE_OC diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410321 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410321 deleted file mode 100644 index 9be013ba346500d092b18a5b0735035fe4a4cb2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6140 zcmd5=3pkY78~ab zEA_ZnxvX*{({1lh|Jk7tMBB7$D6t_SB`7TY1WkeHCkwP>+kJE?r@b{*3!<058j*`E z@O>yJnor{?x2ft$NBPHGX2qMv-t{Y8`FVhsQs}JySsJ0Y3WK;!feY3}#$RyqZ-$<> zWYs+$^N0{&pR=@HvF!BjPaHHEo}TCax3VfvSKrS>&isgON^$MZ7Y0CuENfXblFa3> zyLsK$8Hs~$^zL5&Wsylsie@om^?Z_^+KS|2I~zL(mMrJ{4JX|Q^wZ~t16(bK z2iT{EiC%>x_NDX94nLqBU@%{ov#t!6=*IuzXZ40+6VLKa_U6t{{gSo5H@YQW{Ha>g z@Nni}e^Ka3lZ01YrTI*%hbcHH>CWQ#&($*xhYECSyn2d459f{) z(cj)S(M}J%zs1=7h=!ro(V>?Jb@cx}>oy;lv#2)JJ8}s*r6u^juQc7Vv(=|3Pc<$x z>FL1`{ZC!k32HS4%_R3YRhzC^o?Vy5Fd@ifxdM7(;ExFP_4-zeocd{TU9za!j^3q% zRB;Il)mVGgZ`XdyW`A*9Ru8C95gGYf1kv~n$Y|c+JlM8m-IfL&d?y|l9B5`>U}$6t z2maPW^{GxSkBIbdq;7tP^>&82}B=+{P zojWZYsI5+?J^{ASHB1_JLUaajTZ|C@JO=%PKSA4)RS%y<+Z`?B4J#eF-HnY(I{TFU z7X~jikNm^Wx~X)(Ek)%N8R$Sgbnc}7_ro(U`+@D06XNVz!%3jB0jiy6)_Y?sP)h!*wVRq2~*2Q&6JSO45LTcIM&Y)MWOou_YW z4Rt`97N1tGHmI>>Bl|`})pr|_&W>EvPdpfB=6QaowU$XMvO3nQa!IxcRhlNB9&0wD z=1y!QKTjMj2`lrc{Mu!-E?Tu(F}&fnsEXF1UG`ls)qdRYGs7iTkH7IxR5e#60_pP(thMZR+-KX zR2BXZPz<1M#BDFO?=E*z@fgaFMA9PWy7V~@oNW)6IqP_Ke|Uyyr)lAHM`tn5sQAk_ z=6|z!KrXL5*J!yqySA7Tnctrs1u=+8M(Ef+__4Yo;J~eRy+dio`r4Gq_HT!aF54k35V&4#|&eF*s*whY}h^|UJ+nj(~(0oCb;t?nm&yr zjwM^6lyjn`gW%=UqMn0159eiCQNrfZ?;Ng{I?m5AmCs#_GX(JbhChbI9PaCA6Jk%3 z*NBZS2W*7<=ut2UtF!2Q%n5kFiRcjg`6rH|{=xcw3I~FeiM?Vs5 z9}+Kk7MhM6PRLQ2TiQ3DOQ>5(aI6@=-%RsL5f8ZH-S^tqUe@E`acSr8`1wZv+W<1g z8CaXKhQ(aKQ6cshWIgd06R5(n*B{Pg^LXLhU z*xupj6fup@2|jUC$>Dg8!ns&};TUR52yDWiT`(s7eTKo~h35l7EfK;m;I)85GZ&K& z!-QYobma-LeiYJF*h6afzr0c7?dY`?#VnGwL)U35iF(m9Ijl{$`C*=Dufxu1FkUd; zf;u9^T>vuce4Zu$J^%w3nG6f{p(L*rS|_ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410322 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410322 deleted file mode 100644 index a27642a4367d01c08bea87be95b9955a317b9079..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4628 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 V2`^B4oEmWm4iluh5+3Ow1_1bCZ?XUY diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410325 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410325 deleted file mode 100644 index 26e0997a8d17472f44492f56854ff512ef8e94dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5032 zcmZQzfPnq$?nUjLnc{wG+4cIQ(`Bqrn`XJMTi-ra^g!&Mh2E7{fvSWz{_R^g!RKj?^*ixYdKH0 z*%f)d>dzXGO-YN+{DIiWzzCwZ#tLlOU8~`D^?;T8(uZ3ooa7I04t19~5>UObiRF?_ zH&BT~*fdU^w_oHFHTRcJ-EJTh{Jgey?a%X$my(vO-*x1{!~O$SAq@WZ3V9niH;EVq zNMC$0;k&qTT#OFujI`gqn|E>Wc#5$Wg`~@CDAq4D{k7II@_63Q6PL_v4=jJV&+G7- zOTG!a{>Qw&-!kLG+@5k1*QC`^@}E;oj(AE(Y@3yF@`e?IXsamigKe9ar+{3{eEfob z@fRU@y!hWa+inKQ=hF;>RLGUO;d@HNZ`rIs;7*vYK3n%p^>%CJD*kCIzMXt;v$tO7h1o4n-O?6JYm~~mb$s{!$i+7p_?;YpVITlg z57Gk!;P`_u85n~8Cwt0I=95TM&2r;DmUFr1N~M^tVbAOdMV4$GlfET`)XAPrg(+tQ zn+uFv_5B8p3pZDu7O;^qm^EoabJo@FoXX0Y8qxi+OLp&2kKd#A*4)y<@^qZd3#o&4 zQ#20lJHp`N_sjL`zQ{>ZuM1g$27>)C*F}%rMJD7|{Q8xL{%tLb{dYX4Zd!-wj!ja` z3@RLJra}E63{wwv2*?j$e-PBqz`zDl8{%yQ)~d(vd)HR@z@q@IyR7?^;*>wkwQ{Y# z-nj2*2BrSd-rMkw(9I!%Fyz+Ucg=CFvvi#e+^$dGSAqc zcxD=lYW6FYZz-JI&Pts=N_n1nCr_GA5HsCA2F5@Es2H41@eh2;R3687tlCp)$GxkbDf0sk-}kc!vDzmw<@3H~U!X#!fY6`- zA6JkT2uMG5ExBSAUuo~wU-^2Iqd447l~}wk&k(RMUZ*v4@wLxjRWqhFK$SB>-RjW1 z^X3|+?k4_pcFq4{Q(v3j5Wc_Rx^T4g#l=@cep}6(ba1}#N5SM^qv_js|I-qZ+92NE zVz?u7xyoXt)X#@x7s1m(*Rd7&Rx_NlE}3zMy{7H4$%Q9{N)iXJU_(lc+88ARhm`D^zH9*xfLfpyVu4AvwBEH=QOIC>X8*-XMDW{0A z7nrW$X^3`Vf|S3>a1*lskTV~OI5b$${eT=7$bCD89h_E~i?@5birjbLpY^Tv(^1ug zuz*JG%#VBLEH7)cx(qchf}^4#FtubC9?Vr5qvAO`t|BHR2Gx-2smDIKNl%>l+vT ziR`!_y1Vn+_OIvdm%ZI%*6_UJ=831eY4jIV4i@GdP(B0U{s)7&j8E{8gYm< IjlyCc0J4>EGXMYp diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410326 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410326 deleted file mode 100644 index a09965dc8d64f9d19681d88d6e338bc30c3f7a44..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5648 zcmZQzfPlWeZ(Y6^R2_KveX+w-Rh?U3;~RsoGTk=P(zX+^TWI_js7iSMx_eQ3XQsHH zT6VoY>2w+E)23PO>(;kV6+IBUXQ6lH)tSfYV(+g{UOe$kuAmg(6W+-UQy5~OC+KWm z5S#aK9;Fc;=b&0y{R$jySc~<2M{pAmq_U&@8?>ebFm*K+E)@iS*>Yjw82gG=<|Fvzk zdFIiS*`B% zUiLS0=EG@Cw^g&kokO_ZSUd8E?>K95@bBHJx|Xja^ENSvwul#E|muZ)#9X1DEXS zIf*UG4zsTn-^}1IcX@a{_1P+=u7y+IG?f^M1fHC%ddm2!R(O|^$7A;B$J-!oVqhQ? zS3q^FKn#ux!`F_?Gd3umnZ}};{YvFq3MaR-Qm2nno@d_4lcp1d4MF~55D+`fz@YIK z$Ogw7kOqUKMd!4D43HRSL2-eVv9Ym<2}BB}4os)`2R>ygkK;R5?Wwfm-c`?(`2mOT z`&ooo?UR`Dd0(?HPzzH)Xi$KUD?~GhOh0ukxndSyY46rw`FfM1INVN^SiCOJ5U?;_ zr!{l&wa*|m%2)CXfKC3nA)^d2b6lhFrjSc?4Y=I=ZGuxL^ zRqG3iF}ZgbP1q_dBhbiK=Hnn_XQ6Csbl*RMSE zZ);iXzvDS|(>hFdY?5MTP~liJ4WvHA+X$qdfuLJ}ZVuso0#*wo7{TrXmSv(X3{E9i zRTLYpO}p*$l)K*VpnQhTY>#gz+4Kq`GxBHgJ(TBApPQM#Z>lt7i{iv1o9>>PE%&)h z?e*uKA>6Pu;`lhI>db9WF)FovxJ*$;CFhz6!j8K@WsD9;+27??u&AZf7Lm$sM7-vrodhI7^>Gw!h0v^_TY znbp!Y$7cvUIe&jy#too4CdUxp$RLmoC?F=kN)$*nK$SB>+{xf@N#^b6qg@iFn@a5p zQ_Nz{U0YVATewqBXIsX-q>?|XY8u^s)!wd*`%X=NZj>#WxKQHA%gaGej-y?5u2hQY8urYdP-My0G3i?}G<}Ey)gy-oGMnL$ z+pk+jU)fIUynWi5mRvsni@fdKzq|I&c~$;;Q{m$zDUjQletl>F(LlfmHWwJLx38Zt zX12?fYW#g){m1GY(XuBqy#x$@O5cc8C}j|5W&fpWFuiEslhh5DxK4cSf6rx@?x|nz zyW)$>&5hNod9}HLX0dwc-<)LWebV4!n6Hk}4;}4=HS?p+$rygMa(TLS?%qis!8U@+ z954&!ZWs*`1cd`LG!K9k5s^+I{(I>hBd9)vsUgyQ8DuxX^nz$C=ELF> z_wqx&OO`t%B0t6d+Y5(kE*7g-?Ze!rWaG>GxnA#syVNOuZ@Yky$naT8A$I>Vw1!)BvP_L1My8hm<*R9!#%jE7<;| zMQ31bL|B-Dl@d{xgWLpcLV?>Av~m;HJT^$&MoD;q+F{g)LvXo+lrObG?#-h%o_Ab_4m8G&i^7eor4MnQQS3<%fb4B|3A zxgF5Dd<9Sw4^%6dLQ0rOOt=bMU>f}cRf!VjM7l|Z#%{uzMhA)8C(d+Y^glwN$$ENFbEz~ddtK%!vfC_If4 zY*zs_%braI)n{-$NamqbFi>%n@FULrlsP1rk2USkz#dBcfstR41dy2Uki?aj(bEA) zFQ^PeX+M$ZcMSWH1dy0yxDBaIM~s`KE|q}Vj-YgfVK0&Z5|d;%!P{XVokX|)k^BL- z5y-&ikX_EI0ss0F!&23lu4nE!&zbf$cK5X^hJTh1MD=<6mlQztW2-mN+cxn0MZ}m5 z1N-_F0nl-qH$XdBakvwklX0aru>H8|4dUFi{0)uWgf;IE61Sn07bLprEtTRBy}Uq9 G77PGOi7g!f diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410327 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410327 deleted file mode 100644 index 9f1ccd3ec30a627c95dc0fba75b99ab2eabfcbaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7596 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 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410329 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410329 deleted file mode 100644 index 5a9e0f15d510beb5bd3009ff2f4271ad334f077d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4244 zcmZQzfB?aS)PL_zi3zjM33^%I0~(ZX7cg&8$AF zw9d=ytOUrWq(x_iAvQ8Fg6OM7nKzRHzI*1f&wlj6RLJc8{}-3%=&|izz0pZt{7I9dk^n#JrC;8^={@vs@r)TyJF5*iS8P9c^2q9wmM(FfMeeGrI9?lc7|G4vq|CJO zsO#dbr>^PP>EadoZ%*mXGpmg@r#%TSUbg*fjiuZDXXXb3r}NC_ zf4H?Pgq5e`b}Tr|Y5R3^p3tKu8zLBHOlts!fjCep zD9*s~2GR!t!1&aLu;AhxAifui{I&pL{=dsU6y=|}YI^SXr+_Ho4-;1=tkO9(vu2_q zOb^(6U>wVZytv;rdF|pYy8x^`^qdNm4*X;vQu$;P!ys0QB#6!;J^)8}xShzMgV1q`O%`WVgYQ zSG&aR7p%3AweDa-wMRfg}lbskyPA=71E+o=t_RX9SxI^n=F6KeAg5Q<+5~d462^ zIQi}TmG>fJ?f1?}+~>DpU4-}DyG{A+Rw1Xf_kLdWoOe@7e$CF$SKHF_9xc7>Zo2zb z2^Y{nX7xf1dC&hGZS$+n2u9?^ZSDOVwV~E5;Dyn|@YGGg<*i^#L2(8Fu(StGV?ZHs zkMyMnpmLz_V1}ksun@s?4T~E{+J+i~pkS6EM1W}=SQfzeM41nAAMxgc`~dR@E$yMi z9~i-cB!I+(g%Tv4!g;WC2n|QH`T&%!L2*c~-!be*5v711Cg@qS9-47DCQ4(ID`UWMgkT^(8 zf^i5A6SQ&yQkOyU0oW`e!i$tT8|Elj-Hq&Cl=6uPdl{qb7u;U-Y}g99Yb zA~E68C~ASC$Z>((zGqN4ct3LK`8j&#C3QR4bXu20Go(e zj=(JfGGO@vUXBoK?*Qv`o;$J@&@vd^t;h+I6u;puM~HIMnOi?->?V+3Vc`WYM+S-8 zP|6V!-2_QrNT~uT;*gkd1?X{(D}93Wg5*&0^Pq7XQhp}FO=9o&2TRsVG#&s{_1={gT*p4Qi%r#5Sea*xb`LvO9KYTRmBw>13-j>&B( zYwKLQLjYt`(xS5x5E~g7LG;z4%$rF8-#v5LXFqyjDrENl|BK6W^w{>V-smJR{wG}q zsKlW$mUq%aPS>^5Hmo|vvS~qr!O1N*Z(WzoTD_N1`pMRdCubBaTdHKY?)l9}QrlHJ z)?B*8^|WYxpW>+(J5RXG{awW9%y4ww>zbU73rC)Q-&RoV6!|^(5A%)MrQhcy3NL&2 zclYg+CMUkG3O=*{`~Q$vUyuI(d0c&EeMsQC9P$4<(jr{a7(`p8cpq%rygUWuV&>x) zs!wkLu^`}74vU-@TC`Tuhky7LQeCYgu#Xqf2q{`|y{^6zhIP)q}t z?CCj)Ey@nFuNB|S;4gQ1cs=#mDy6Q4Q{Oa|7>NX)oUD4v_^MWTmy*Y0_UOmkAZ}t{ zAQV?Xbxcsq5cEIUQ+_g^M4D=r8~3rC%RN^r#dHmOW=|-xWb2spEt!Ge$pIJ!qCoY` zKnw$*_yflwLH!I2Y#_BE-iBbk!NRKl`p){suU1Q6FMmF))$L%vf#MeeVEzTg7Yu;Hj2RgJpzr_#BK*%F zdo~pq&Q4l!_qp)AGEZG5`SO>3z7g56BbI4v<&CL z@+Q=OXyq&<-$LZTW)Ts_@cc?d`h__ImX49#OG%g`n*+83NdSonvz~-7AwL~}>_xE~ ziG#!>*-Z>zTRq%N5v74}# z34_FKl!O;3ucO2j5(kM%Fb=`xB%yMIi131!BSh5uFh>zAM~JYOK?;$EXcs0(

#W b0;NGXK#CkBCR`dtEl?D>Oh;~4!!-Z^NQu`g diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410331 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410331 deleted file mode 100644 index 2dd6f71e8861f310ded735d26e1b1340a3a5cd80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3124 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 Sx~Unci5hW;UN?c=0wVzQ5z(Lk diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410333 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410333 deleted file mode 100644 index 96e0cb0c76c969778c57e6d5a7cabc1fe316e678..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3608 zcmZQzfPlhRYa`S;6D7At?lUm)kBxn>Zh64vdgC(grOq-MQu73Ws)V1;f8WR@vNw{6 zP4#!7UhI0Qvy8g}a-*Yt%)UOhX$fcCKmWrmx9{IJ>ZY-!%<%H72t1@2*YoSec9*W= z4a@76e+JozeTCjfPq1@RhIX`w#~~^KrUuJeqqN8 z8xRWuPUQjV6b2t}2N3;i?L9S%oi1LX|K^nLJhR$pbJ~;O;$_>v)>yjTe`bC#a5~Ry z{)bz;<<%FO{9LDhD&g6dvi6mKwv_)rXQ4a4;AWC}c#npOPVdi83@QKqrUu0{aLJyY zlh~r{F#B5Z%?$o>mxtF=pRH2rS~&GhQ;CsC;K|9Vr;M*^g?A}=JZ6u6ybaREso z20-x#jzfa_85np#YD2t@z#m)sh^?%Q}=PMc(%A-(CCXyefaasqk@<6i}_WN7)OI9U#C6b_3AA%k~CObg`{jXW^Kj zeiYk4guge1~NhJ zhXGKSF$2>CD1U+h5&mb8J)0;2)B_4bc(_5eLlP2%1G5h%1){-mge1TWW<%`C9aS-NK9C4;EY3Xn4r}Qu=oYZfz2W! zE=kE-Fh{}i7_xgo>6+YlqFtC!<|dH4-~h?9NKCjiidvv3a$F$S-wgWqH+-IR@Y$Dy z*^-ZhGOzfAC8ZUMFdG(6Q#F>{DEP(8Swg~u_mbqHHuc>_>0 zsQv)eBgg>cPf%P-zyyhLht#Fw5TG7VT?h&nl(0eyOe7}EbX2ua{h+o5*nVL8=Y^_7 z$&*C6>9C;)jok$DCoH_+d1H{cjgs&J*N5;J0y2;y4v7g@ffC<9QCxWgq?Z*ekCbmo z3@_TbjWRbu{0t2eq(A~Qp=~y(EY38KUgm?_*g#F-@FgakXiy%2$^tQ<8^Hb`!VRR9 nMNA>wPZ$_BF507a6dW{2!3MMs5+C%k7ujwGX!!_>FE|YV+EPsx diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410334 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410334 deleted file mode 100644 index cb69dbd7c2dfd50b10eb0cdda083c6f414debeaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3660 zcmZQzfPi49gXWg!|L%4b=Jr$ZT@!MaC27msc!n~itG-OL)Mm8+RS6fqS{tF(nJBqE za-V^Te{Af7b;|=T*Bh5{FLjpDkeVmJai{(N49^J-=2QMG_A=TX_VHK6Q{UssFIrFU zn8sAJ&=zD<(xS7v5E~g7LG;z4%$rF8-#v5LXFqyjDrENl|BK6W^w{>V-smJR{wG}q zsKkL?SYywY&QFd4Q?@7W)U=WnD6Z-O?l9$2%wO#uvtyLE4*Vv9%=svh(xmnNe-fCgq#}iL)TD0)M zm$yAr68bp(*iUZDJ!~$R%)O&U?#tQ(Ti!OuzxGvos@TdP+A7EUVB6;9DIga!AHT5s zYYm760jKhTbP9uyw*!cNw)UQy#ZDKm(0_AEcb-{ov^nibaPhM3Uu!Jg?msg>7&x70 zHvhw|-SX-SO@6M^Kb7!oOIiEMKU>QGpR>@NUvM+YJiJH4M5p)XCx(=Ne^Y~E8n|Rn z&q-`ic9?yw_+|!wxy!@rsn1p^buFCwrm4h8B=F>9)l_e9Uyew5!I;O<{%uPz^{Q zST8~Qpz2=QUM_zVV5=FpMmNmifV4blrw_;2TWrND(-d~ zzI?juoWSPf__s$--4e1kce4`wBGI>K?&Wt^jr_ADI@IO2A4%HP7 zt0f}dyXm*w&tnD}2ntVz-KyKf^)#Z59TPw8xqmgrQfO-O;VGLY^iDH+bZ5DkSTqB_ zlLIh42?CX}fYd_)JZuQ+XJFs~>R}A=HUw)87FPY&ch)z4wOaam`SW2Nw=@eBml}Ui zG0?8h&X_uX14OM6SnVOVU$>0DvYpm>`?NJJxqSW?dE2{xckQ3^s{Hk)!pBKcAVq9_ z*(EaLp*@LOH{m40B0f$8o)5CGY*G{*?!{(?FR6yD6huoQ;!38!NQ1~HA!)=5C) zKxugbP#-T$FNlU&g35%e0LL$!2eKOkp!O#%I`auC#|SDfplssY)cy~sm!@ul<#kYa z4K}w?5?-M4h#GMS4iluh2^@XDH0GD@owUkzu6#(AdNJoQY3WZ677ghwHLtiPR(Ugg z04oBQjSv=?gybD46G9P@r-2H=^$5-KHM=?=$T6V22g=*X0G5v=VS>cCSL(1~1u!jv z$}xD^2h&exJ_6ehj00GHMoAY$x#{4l8#Hzk)_gQb+(t=wf$AcZ@{P+2#yP4!f61@4NzSI%Clgv6X8~1*+zUj1RAX3 z9%U~;Or+oivLRtaFMGlEK-)!7XTd2@7>K~!M_d>X-ELzF;eNuvuyN5Iy`y0JC=3IN Q>_xVl0a};90|CYW04PMe8~^|S diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410335 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410335 deleted file mode 100644 index 5df72efbf5438932bbd3077042e02bf9047c18bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4236 zcmZQzfPl$A&oWi6>d9@~-)P9%_H4z^6`4=T3O`?G9wmPis7g54>7cpg`M8dZ&EVWrJlKE5i?A-g{s`2`+*RyRsZ7TJ`?`>OrbjS6e zbsVBxw+?`8N?LT*2t)$`BZ$} zKqU^b#Vgh;pPr)H@Ha7`jw|%qy~@&5*FSqyoPA!aS!UMU`lII^WMs?R`(^bj?QP=R z4VtGO9A8mZ@Nsq?W9(CH10K80llXRO1^HWg%snA}UN&W+#FTD7$NA?Lbrj#9s_f^R z!n0~y(hKjUljZN3C*)3A`gNKwQ%a2rV=BOz>||zPZ?j;3hz?#c+4LCcpJn`3=D+g z3aE}5h?zj@4PQGl&)A@NW*UoX_A8ZdDV*HSN}WDRd7gPEPnu2;HUuh3VGs~I&A_1X z0muf&8%Q4rBrQ4@38X+`oCU=NR>sCA7N#HxggUVL6#u}dOyzNW$ErP*cHFz_nKD1% z@O?jv5UYI>Q$Fu&_64eE3J47f@Nos}1rzC~t|eE@;w$al`YT^=aukQ#sS=CVQ;wK@oy#_Q@BzjZJ0GP<6Babw$90)Tf^H0l~!%~as1w= zk6*uTIC}Hc+sC(bHs~F>H|Muz%+1IKzI4wMvq}z&^rvwE4Frb^K{qqDEdaV;D+AN_ zNg$`d90H<&>D&iMvE1=<7Be~Eckju?i;{X((m684Dz+^jGu6iwy0-Wkoks;CoKb<}44ZeOEMtuL0cJ(zJhDv;^%y}0#{ z4zX%ihtzWz7;Nod?H6WIwA^d9+Wg9goInG?VHxy4*;9TppG2B!mK*o6oXb5|D#dgS zduC54vSjO+^evfz-^l@(&qRUhSzwL;((te$sGos>2c$m48&bR+a{G15=quZ4owrY0 z(~`^Qf04Jn`*+v=Ij_oJZz_D8Bn7jB_3J|rlN*S+U}8|35$rBt`IFj`qvq>zQNnoM z+1~x8NBbNW96PI1#wb2*-G{w-Li}s|-7Y+SEk3tL{_8Obo839=QKu(8x+YVc@?9?T zveV(;ApbMJsAn!<6mq!WwEU7n#)3*`t&>~W4qUUUJ$w48?}D1cPEb2j{sRG!4UT6J z4dniV%7M)RhLHr6PfWgLU|+vn1)6u?1NE`O^nz%ZC8$ie3UIu^d64pg0cJliee*)) z7(wMDOdSzr3D8Z;4$#<5Ah*N9Yp}VElJEkRzto6BaF`&~#o*{WV754}v%l&3J?83! z39nLeq%4;t#X7#0aQXRXHKUPo7+4XoF2IsTe?jG7VJ-*dGY~9885qPg+W&n5rbbXX zIuWQ3maf1?keNoo_5=L~s~k|moJcqI(b!E`)94^^8ztcdstc(Rhgj3-6uS@BMkhn0 z6!WM4J-Tb!8Mlca($p)t1RSMOubg|jYBe<7fm>=oHZ1vo>IM`*M12BO4{qC$T&J-0 zl{Wx2gX$Ady@Cv2`2$}65aSN1!-f^mx)I)HgBc3*Adrv5gvmncUN{d?hJ)<~<_}n1 zf)d|Ex=Dn_Zo-;B28r7!2`^Cl2IMz5K#DjdCR`dtEl?Dc20-;Ndj0_E1=S7AFgcJi z62psjZbND#kl`kXpFti10;E6!Gofubh$LFr0tIn}7c30H;Y*C0Xiy%2;tG@p!Tun^ q4WyJsOd;G)7#KD#+M{v>g$inuR3=z`ocDQVGJbBK)$j3D}IQRdC0fbX8U?6V)eFcmU;|Nq71IeKjSS8sHZ7ypwk z161O$kTL%9`uk$)o`3UZK7Ppf2W{tok%{SJE zc%N%Ysa;j^n$O_Qt8%8tJBhtNyXx1^RqMr`h^?w++Za1>&APrM>C5#sAF8Z&C_hxX z?E2z;X=*v6=)p^?Ry=rn<&Ul5{-E@#r3xQP8YAxe{)KAo>^_QIqgYs@v`k-Yb@RFKQliVIGtxU z|HG}_^6Cpsey-C$mGEp!S^LUATgv~Rv(TMia5Kp~yhp=Cr}yV4hLnGQQ-fj}xMWYy zNo-Men0>AIW(I$`%fsub&sHgQEu8wMsl-Sm@Z@CGQ^r@d!n>3_9RNKeEWXm-t-td1CP#6&ohq?-U7jIeVZ2Uj z=HhFg!767=YXH+gH$dI$uqblNH^o}%=KAgH1h+V6ns1ihETDb;$izas^pdkV1=|hN zH%*Dsoc*V4Z(sSduHv#AmpPf@?0cED7ME6AMKiGh%>#uE13@=4wk-f!yOn|I`(&VU zn14Z9LFqgYNU_}Ua~3l>;CJuI#fy@9Rnj>!#VWQfA2Z!A?W*x|Q<&iZR0GmSY#4#n zy|let{wBayGn}(7nQ@1`rtPuG&#acNIX*++$@%-sGHw9PV{#1fbO{17V1S6QlqjmX z1yjxljT46ke>Jve<*P-xum9fh^R8=#e2)0+HA`+esS4*ziIZ&knNHM-<<$rsxF7yv{v$7e%hROi99(}PddhUM z^h;79pD#K=Elv3k1VA<{92tS!Ur;$vd@uv^p*)mNIBpmi#5CIf^#P3o#m^+5K3aLyjb&iiS|7YR!X;PA*05EuYueoAM=xD|h<-7WDU>bl>q z@~h5WjJ~ka*G1qxbBn}{nvHK|pZsK>DYdPvxutBrnzN##*DSF=_OfKvrPI)%Z<+W|yBTYFEM7%^TH#$v9*^0hA8&)WiGhJo zTmjXw05KCt{i$!PVcnu#ipA153&mglXY}^Eld{`w*@b(DH2n9pdQD|u;NHQ&tkuTA zT-pLu4vsgFJ~Y4#vHlkDb4 zo&L6<=IZgiw>ZT2&$Ciq(OQ1r$jcq11_-EPr)!7@*f6y}RsYJ=OU<-a|Jh_TrK!s* zdi~Gqrx#~!aqWAhuub?9SP_-%jC6_s8#gh{;r*0jC9*7P6ccxA0xJ3Phb1Vuv z&C|jPZ#W-^+Q|rs4+e)i(ddwux*PwLKHTqhzmjp2&nv-87Pr~GA~?5}FREr_3_Q8} zb^fGHFL!69A97q4;=*b8FXq7BpUVq=hRzHZjb;U!2abEg*N)6HHYlE%#-f`2O66M$ zC%3awr;k#eXWq$^rW1q>f$CBi1jJ4=Flc-NvQgqbY0)`QjsS^q78Dm)85^5e7y&sz z08lO!>U8*%zpuDIhc`z{eG=7fhs| zx|Uoqi?6hI>#uyh$x$3`r%EhdmuCoA7_ZZsx%k>=u%a2$8lXBDp>B29*SgN@1uNI_ z`)m?(L+9$wt*Yx&+E;ph`J<-n*n2no40`!yS{B}smRA=|`0i>w_vXpTzAJqDJhLVx zhu@b8{RJ`(94-YK6I)}0|1Vo0$?nYdrBv1Wf?`Zp^8=w+=^1C<`W-C;sss8x>?8w& zBB)%0`4^-gRK`Vt83=Ju`eY3ChKO>gzSz+qDVwlWSVo|cugu3m$j(C9*66-(&yC)_ zcg%Hxs`k0O5(TGiBHY0k;0nnGXFP?{Y(yvK{@EJEu)4@e^Pz4>H8Fr-+&kn zfbkIq;CJuI#fy@9Rnj>!#VWQfA2Z!A?W*x|Q<&iZR0GmSY?=kDdue;Q z{7rzZW;kbEGUE<=P1|FWpII$kb9{!tlk@kNW!wOo$K)8|=@JBFzyJ|xTcW7u7EC!K zG>+ijH~6=cdtmbACbSzmU4V^j;)Z-{#(2BKCAwhl2YED!0uh}m1X6@ z!pko%iD{l{dA23+%$8hEqfQ>6fh^g=M>+xz{eR&TZ`{HzeZqCF;LhEBGqPICQzhOQ zR4Kx;ug-rU0IG+V=|Jv3sDpTMutD*}46G|?W*fbdb1>lJEkxDX9^MSktJeN$c(lTJKZKPi}Mgnw464 z)_zmszwIJNCttnhSaQzsH8d@tr%_Nj3T_|+ld>yxrcgNEzZny zkykqMBL-ws(xS7@5E~g7LG;#Gfla$>HT1bcy?h$mDrugPCBIV@rr|ux)uksUj2?tyUrlms>J(X+vepdAQv+qzp(q) z1P}`XP89&@6b2t}2N3;i?L9S%oi1LX|K^nLJhR$pbJ~;O;$_>v)>yjTe`bC#a5~Ry z{)bz;<<%FO{9LDhD&g6dvi6mKwv_)rXQ4a4;AWC}c#npOPVdi83@QKqrUu0{aLJyY zlh~r{F#B5Z%?$o>mxtF=pRH2rS~&GhQ;CsC;K|9Vr;M*^g?A}=JZ6u6yba&A zjyE6;21$#~WdRu=G0uYG0xM%<6LV9D6igkMPVoRNKeEWXm-t-td1CP#6&ohq?-U7jIeVZ2Uj z=HhE0w=gjM`p^KPfq)U}RtK3wN8;Ak6f<1aJfU>++FgFtH+k3Zy*qfwBK7y>NoyE0 zl0#DqIqqzkW-(#=x%?@&>-yUBIB$J8Q~xx-;6T$NO;(^;ps-;e=w`;Y1wd=JGBACg z3RDjBFGwpWoyP(xmc4V{%5B>3wdCPEo|*b4DPLTVuzk62I{ncmot%>G6HQWqYC!sk z4I{9+m$sM7-vrodhI7^>Gw!h0v^_TYnbp!Y$7cvUIe&jy#too(OpYO*enCJ63=k8R zjE1@}<&4lcamc8P)m`vk)Naz6D=!stY`M72uAbwU=?naE(df-fKaIM-j}E+FeR7Mt z@8_uS7nh|=V|u;YStP`Fs`F0#v$*3bAJ9OioHb`Se|+R!yy~6X*Lc@swNX1Z6mHMB zzFTI2_f5mCR?DE4ru+v2AR88rj6m)$s2nIhn1T6F5y~eVHw+A78ts3N0gVI2&lI3O zUYK4G4YLH530DD*e>e|hHwZxO2ga=}RE`l;HbB|Lx+#gqZUVU-ghAmo*xW`*c!Ba5 zHR2E)CP?)VIQs53%D682XnNn>fva`z=MO@zO;--G) zLFHg!4o{;*l&cKv>zDq3maU(F=77o`IG{xuCDKh(XzV6XSi!;z93LQ04-&Vbq)`&x T1gev$5r^O~K~JNgFaiMp@E?(Z diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410339 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410339 deleted file mode 100644 index 334ae0a8358552e08aee2bcce97900ae596321d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3772 zcmZQzfB?1BYnT6aT;6fm)5Sor|=I^~0%ug!K<+U!Ec>W3jsuK2aUOUy*?s&N6 zHFXExMH?S5{$dj2ea!Za$Ap&iX5Qu>8Ub`+t6GvZC{vesBFV|MZLUpq>r-M`VTE7@x?dNJlNM z5cl?Pb-T!NviJSOEzb+;d06iXcHHTkxp~t@_9Y1ytFGT#tY>sJIBrNJ z2-fOvsC2Ely@tU?AwjsM+~l$FxyU`A7}IY}^|Nl5EoKmHRpx!LZS(RJkc*j*U)cS7 z4~PW;rwV{{3WJZg1BiaM_MV!>P8YAxe{)KAo>^_QIqgYs@v`k-Yb@RFKQliVIGtxU z|HG}_^6Cpsey-C$mGEp!S^LUATgv~Rv(TMia5Kp~yhp=Cr}yV4hLnGQQ-fj}xMWYy zNo-Men0>AIW(I$`%fsub&sHgQEu8wMsl-Sm@Z@CGQ^r@d!n>3_9b{0|c2EGRCpGB!3b2WbETm^v_>;ve{wsXUJFShc6pj(b-y}7ENv$6aCW7sw_9=Nm_@otvder$+b4G zgN;|ZC$n*We2`kVVaoOgoprR#g}S57m>H4c!mAVUednXzpF(3@Ksn7&T~ zDu?+Oq!pCT6M+=V-Z^jOHtqLX@^Bu{OnsA-FRn+}zT7vR{%DgR$&g+&{qsG!Pt?oJ-iRWd51j`BS`M_wjkYk5nGNOKtsE zSv7-m{>8H8H_kHfJ2^0LD>eevPX=PJKY=tl0EvU;1Zpp4>sT0jH0d?UeP4B6C3 ze1?#skjr**xou$&=D;+X_aEI7BR^Y`Ym?X2B9V}$l7k%K!9AzS{LeNDDE)b~6R1wy zqwEDtITP3|z%r+?K3|>X$V67h^ttipA6ZE z@!!3dk?rqEzeQhtZDpTEa>JE? zckgyhzwk~mOT$X<&?>g<<181y9<8+2xwCHJPUFYsAtxAZdiGoF&D`C@3UnCr*L5=A zLpDB6zOnUW-@#vxb>HZ#6n0MZa^Gv(`tDf1rytbuDgS{0$cBX-Bar(GDhG-KW?(s{ z1mzP>+YAh18ts3RfX0E+_f()hUYK4G4YLH530DD*b2txD)-b^A2j&fDs2n4xY=x;K znBTx|`ty&*ZUVU-ghAmo*xW`*c!A0&YQ!NpOpxkvaP+CP_T{zKS?i_8U$x);Nvh<) z)h?;MJEKia{}wZrZc%&%Rs<|kv7}L8e1ZWi%$1;gV(KLZ_Vr7rK`=a+3j#-Gnub4idMaq)`&x1ZrPUBMz~qQJoVhyJufq`BtgVuyq?-=;Vj;Z!7|T z9qZ*ytynX4iGMFN;ecCtKsHkHfhQ?w8qEdOv0y;3UIVJK`f+UnUqM!#*Nt7@r(oIG*b`#b#I!N3`NqB+UCnx|Z;*gkdB{<>`Qnw(L zqaeMY_yyHF;xOF=+d1oQ+VZGu5(TQ?08FwIVESM*76+mDoe1+)53fB%ius^=9-RL` TZXmk-g`@}Ob`Xul{cvdjVS=py diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410340 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410340 deleted file mode 100644 index fe15d2001e013d07a703fc6214c48781f6dbfaf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1476 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 kLJdNR3*y{#OP0oN!kTsmiQ6a%FHqZq8gYm5 zUjHZ%6ad+jwCHRy#6|{25Ph{M^JY@Och6k**^geB3YoqC|Kjo-J+}R;H#*6S|4Ekt zDsfQy#d*QdMltJ|n{9#Otg^>NW};_A;%`-~73Y%U`T3eJ-Y@)!>8c~mOQJ76diyHx zZ0!S`sjEHLE8O^bd!E+^O_uqeOY*kZ@XZFYIBs z0AfMFsRAIK!rBbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}PBSoQ`~^nabn%j#Yaq?YMW3?kD{T}!T*#aG(9^;f>$VqY1K1UfC)CCxX{W2IB!`1_p!~6@<3QFfSP%#crxEPukm_qp= zX|URtwwKG_1lVeZbJis@?y%RiJvRB7)zUS`X9zqwe}7rV4WK$E#}MDhAdn6yASO&C z3ZxpK${8W8{fYPUXj(ki*N5iyW4dW z{w??`Ui)nGf*VqWKR>MEWLWpvdNK3MC^iwx-r zV0u9`%o0>4Tm?8D;XIJtAON)=7)NnXIYv+(hq8%uQ`Q+8y9t&*LE$yn+(t=wf$|D9 z;t(7rNc9Og`oeyh?wpf*W=m3C{=IoubiAVeai+XjGVju>ZEqeVIQdya;}}~S{Rfr9 zNTWoQj|}YV7cYR8kw1XuutLoOQ?y8h8fdBvi diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410345 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410345 deleted file mode 100644 index e2533afc30ecfc1ecba5ab83055037d492c51124..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2764 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 aCv5(W??(H7kzzhdT|;zVf`qyT=0^b1i?_J| diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410347 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410347 deleted file mode 100644 index 8d9b81b6f86fd67869dc097de9917f76643a8f0a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3700 zcmZQzfB;4hj@U1OD;ivW?6JPEq*kWb@2*tl-qKqMCdXLU*6z~-suG^E?|pOr$_bhB zH;w|q+uCdJg zbo926wJ^x0q(x_oAvQ8Fg6OM7nKzRHzI*1f&wlj6RLJc8{}-3%=&|izz0pZt{7I7LDJPS!uhQ@G3w;eVk8=F`CS6P`f2Cn2U--*PrE~o%J*#YFSEXLnEH;tY`R|Hb zuuv_}xBGjNvKsa0-*~=w4HKtxU3T)dOMYodzA`!Wsvn=editmNVCbJzO^pScXZ)Gm z?zn8tXZFYICd z0AfMFsRAIK!rBbB|O_w*1q!3mh%7SEOh4=+)OeL@6j;P>HYbMA?4rS)S#FKF4@y_ z5?hoVW?w75nZaM~^6+}@!pZHd)aj#?=b3l%r0E1L;8WiB;3f2oI(obDWu9(GF+Pn2vzTV_04!2V!7O%@Q1T2i# zY0X@G?K4=>jA;!}9gI-7I#j=3VRZfe+1F~Z46ToM&A1z@uq~#Xug|USg6#3B=Jn?; zNB`kt_{a3zGlyS9KK+u6sn2S;m1$P`@z(XKp&g$E#RQ~60_DPkSj;lW6dKBj}gPSwa`T$RN@H1lkaQl^*m3HNyYaLUM92fd#&#Ir? z?(gJOGfk+`D30MIiv!5vOus%ffM_6KgqX|VaHfl+Vv}xmmsxJ)_vb;=YG3Pb-xICH z@}~FgRhvHM3r<&GZ25HaijSoC)>bu#L=La-9viYVWMf@UGo#9P zZ@;*B^(JYS|L&DdN4jHP|C;TX=_PwvSKBcbY$GUrLI6tGL&ZShzzmHiun^&RWf1o$ zd%=LL2Wl3W!eR*{sEmNAAJ}=v~@n68YY<=DT zJ3Z|Me4z17QoTXAE``?RkTwC-3Iv5EVWNZ|aptGM$`6FWP!<;Rv8Ejw*h7gwFr1Af zfW(A*7gt_JPX{2q81)8;e#fvMNdSpShTD+JTVmWKb*V%K+Fro07fAq#NwS+z>J6gX Qd`SL)+X!S}a|lcx0Q4D6c>n+a diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410348 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410348 deleted file mode 100644 index 98c5b3fe96b553f8d5f91a1545e09b1aa21a8b36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5252 zcmZQzfB=1wj`;I9#BlGVmE)VkA*%bAU;l+v8vi>!Zt;e@tXyCi(A1ar0d)s7ombUlzr!4*vt^QSJ z)f`uuC%jCTtkwmv73gf~Uc)2ZY`?DP9N)7J6D#f+Z7vfh{1KO2<0-PvR{8b)FB`(w z*j)N^GCH1pk5}2t`P=iCttwY)dDoS?a#PMprGJYml&&&}w(9Uc*tU6j3dqIG$1m(* z^8m3R;8X#SPGRuzb^y`O*4|UI*y-XG`fpC@&NHixHm5xaE?&0%YmKGb{b%L}1E=%M z=6|@gTV8#k$l#E|muZ)#9X1DEXS zIf*UG4zsTn-^}1IcX@a{_1P+=u7y+IG?f^M1fHC%ddm2!R(O|^$7A;B$J-!oVqhQ? zS3q?vK+FVEU!XCuH8%MFvIUat&TL;wRjn^5#&k755Q>$aaptYx(K4VCpwGijGB7AE z2eQHO2GR!t!1$a7VZp_DfqceLZ-^*|>Wdu>lClX~g=GX9`O178gzPMoZH?~x_T1>* zd&gWCsA`|fD^YilY9idh7~l$4%5cV0D9uK6V(y=`B-;TEBZq*PkAYJiuD{5UJb%GGLhk1AH2#ENORCOFTQgj$p8G>~ z$JYy7VjD^Y*Xg`5=Q4wvGtv40Pj~P$1_pHjV4Bo|sYmiFIBp2*XJ7+`Nr<;0SnKUqVpiIf zf39^*J#t*=n?0+3a=X8iQ_VD?Mx!`}lPnGl8yD@-I|{W0s1M=>1_!5Kn}wnaURJy%*bNO6f&sBDIA z6<<*m+mI zA$?Y3W~0L?evq*sGf#bE4eJ)|QY@CfSt$PUKclzTos`{f%P!nIq~X7()oUsP1NROF zX00{`=F&Exa%6viw8H=>4S)bB4}kzv2=@~(gRuD!^=5YUAO^^M#?W9FXAp-&cAmqQ ztky|(^P^6GTTpZL_}*I_;``@WDX(ZPzi;FP$xu|X(=`NAG^+in`d6l2YNoaN&nBZO zOwjK9y*O)&Yu_t{ZNis8?g9d;_%qTe0&LjCG>7+7{_UvS6L}yu@ZXs>rQ;Iy z7tXOL=rm6YE4<-+9IOZ!E|BCzO|2>7Ea4{ z%vrFbUTu?U;j)FwEs{bj@|f4>FilGrT>s?srRkC%rb*6Y1)9h5yFNeeC)P1#2h)EjgK^T z6DX`;;WgOYMoD;q$_i@4AvjEs+Fs!3doG{OA-?Z*l-bQos%pWhXN&Id2g?&+BVd*QIY>;H={VCU z*nXh@Y@sSq!kmb91;|Y~GZy?*yL!(pMX+b4NhzWOIA zzm;bz*Ca)|dsR z{$cS8k^`p)BEpOKwl^##A===`X%5sr0J{mKj0k&y=^CDfXcs1wxe3{S)QTsDJr~pu z>oFXAENeJPAZl$ai)a1h5~i>-f0bt0FaNjAsSX;<=;a73^g%Qzyg=a%FGmRXTNoH* z&!#dU>p?aU#iI}jlr&D9`6+WqFdu9Frhz?__yZ$YkOYvJ@Q_4L$H@5+eY^=IhmvPV z^gD+ANCHSqGTergXNYkVw0=VG6N4>AatIQWWH*7*Exc?Yx_^zN2W}&ffz2T>c>oKb B%Xk0) diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410349 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410349 deleted file mode 100644 index 26069739ebbff90e84d7a7706147876961d00ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2888 zcmZQzfB-GFgo8)+-V`zYbNgZNS%Yax?ll?jf33d0Df3y9?9R&(Kvlx}A|3M!R=?T! z&3F4ZJ{E~227#pRJvn8iGV7oI49l6qxX$^Ze#)~g`XWnHypwHQx4NB*nBc#x&e|u0 z{U&4EeRq&eNsG?bLu_PV1kqb#1vc%j)$qG|z{-8;!>toe@`pEvy2~61sNUDaa>=F} zsKnva${oFHPei50#--joXW{(7X2PYs#3g5DpF1hMVpr@L78Uo)lNKzfT&{3A@2~gq zQyE{M&*p7>cIxl8LvsQ*luqT77pSSs3z&L-%Q=T@oHx8aPkZq1j!T8f-(ALBx0dj$ zR$Vp!GpQlNC-;!hG_GHVw|}YJ&SxW^ob+$uet$`;#a^BaqOH2T54LSyo&s_)^YIIN zLNY)s2sl*$q*EAtyd6OFv$glsEOxqhh5nmUy7SCxqs?hgf{T}J|5{_|cK@0A!NBP} zv-uxx?Uq+xX!3KN{;7m#Tguv3{@GIg|D1*H{DPZF=HWdWCOW-8KQW~I`tYT;5X$A&$0bm$t!_-6V z0L33T4hidLU<0WQ@iqi&?KbY}Y4>8zHT=sTvo?0d|HH}eSGg;PKTF%ZNhH#clapcN zqCI*?p|$|^LEOOLpy1thdqs1=0?USi($1H^qHQ+^G#7F&ds@!>F30`xSFKGqS3dt? zZ+%Io!F;)Fm)AqXug;mbmoN7Gd^KxQfcrX-TS0zixcy4ZO1tvUwT`JrjthOWXVp(` z_jhutnI_a|6vuFq#R18`VE+NNfM^LHORr={3s=`t*GhNyur#kSw;X>bM_XH{JdlEf z$Mk8wC-`_in9BeB%|5Ae({a^DT#w>hW^i*RS|8x)4t@qw2MY_rZed^w;eG-#8w403 z?qhIR94d4C(GgyUrwUwqSC#Qe&;9mK^o8vn9 z!M+`}%DY~Q&v;h+;7O**hA41YT+P{Z;uzc236oxUf5>51Qe`N9ueUrbmCu|;?DBeKzY9&-9EKI>%;@srRLt{5#&0~Ya zZIpx;$X_S`DdLcra3$#K@#RZoIj~togcrPCAy~)4oP<4ppp=C~*b7Y8@HB+(N8~b{ fvM@m^pUH3&irq*YBql6SaOO2|{eV<{!ZiQ@RJq?c diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410350 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410350 deleted file mode 100644 index 0a8b820ef0c159a91e162aa550f28f165725e6e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5600 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 LyS1C5T6N diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410352 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410352 deleted file mode 100644 index 3a972c16b1235ad33e1209c86f0f0d89a7239ea8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3936 zcmZQzfPl*Fvy+$JofqF>9CcUd`_W68^Srs{&pu)G{?#@vU%y!fKvlx8E8qS#etfgQ z?9bzM1(Qv7Z`vvDvv|7CY&ktsRm0s`N~ww0=M*j39c2%2|m$b4%HLHD^UfuUTS!c$L0UriG|&kN)hfr*l6T z1C==34C*>AJMCT~@0ERRVZAMU65q58zehY)SALWhXeMA`qxk%LSJkEaH5+u!z1FZ6 z=_*R-J^0^j!o+zq_cY5txxvY5Q<^w;=lbG5U-N`srQCk$u*xta_p%1>|Dp;};HI zS^;7~z^Ni2oxe1lI7}h-4Kka$KT!Xj3RJ!|WODzns()zO&UnI1)N#)^wiP z{13Nw%d0Om`MFO2RKl|@W$i2fY$^YL&O!ObM|@E#2lo!+0H7*hWIO$~}^;F3K( zC$UA@VfMA+n;HD&E)TD#K3k>KwQ%a2rV=BOz>||zPZ?j;3hz?#c+4LCcpJn`3=D+g z3aE}5h?zj@)qA$iU0mnH{5$4s|I*KLeldmxk0w>~X_~)GzFd&F@-M@TX$`K>9!c7@sR4EVwuai0{QBzb!zR|L?L7Mfqp0nx6apDIiMt!^D*dt8`AyteL0? z(*rgi7{@QBJPbSkN!oO6`SLwUiQ=5v$usHeUo3_<-ht{gRYFSK`sWy=E6mKGb%ZZTuj=T(z+3V7Gkh zbsz2fiOYU7@H;s$a4R+f)lUXu6u$uZFaQz<%L&w8%+|3m_Gr>;l>5HwyvW5FUHJ?l zMIo2%9?XGh@G}-UYd#v%YJH_tZZIrQ_yg zkK;R5?Wwfm-c`?(`2mOT`&ooo?UR`Dd0(?H17q6)V9;!3VER52s0StdplN~Sj-Rub z$pOE6PcB}R)T@%tkttTOZTXn#erZ>Ymz%;22dF-P?RaT>x%^Flt!6l9T{7bi zdrjM8lb=~FU2}Yfz?1X$mu1`ln#trC;^`6uWWYfBscXph4DJAnTxM|2C9=Ns<{PI&ItA&C{8Yjf7I^xirxAq`rab>C2wwDU|oAT%iZB? z>pQ_u*Mi;he};=4J)c!KY4@8?$EO-UIWpakbMDF6q1ka-BA+jO1*Ju1-Zm@wN1R_j zf9LHx%l_cV^WYhOA7&PRkvTYLVtntMhB&aL;IM?SppF3N9UxoWqckxADh7%dW@!Ec z3lYq(u(SrrvruCY6iTE)gc(6)983jK=7Zcvy!jwM!2Cf=dnoY-MzA0WATeQ~1j#RO z9;7^FfQ2JkJ;wr62Z}>-{f=Qjk^mAD?ix^7BLh%bkIijxbwtED$o;A?LkX4dJj?dJ zl^1hr2dduy#29YG5CEw`3LnDe?_){tUi_Q{^BI;s@u(E(Q(omIcF?C*Mn3pk@4PcS z=5wM#=5NrJ4u+P^z&!aM2$0;&2;}|(@<9NWhV>y_V1-YpykuYy(`a9J59mEmnK=Wf zj~AvFL?eX*5)-Zh9zReKSUiI52d1$us5na45#^>f4LcgU3FLNIc)`>CAaNTd;RUMq zs1b+YFhMFOz)^W|mhSC&&wn4z=(LeEZ;YNgAwK18&~(?vvo%WJ(j~bS!HO{J4X`kj zfQET4ykaBRCIV`-`g-pUv|Tg_*)R|rDPbZp;i_7pQHE0+1pOi3wMNBMu?;6;c`n=>?TRDD4q~ZRB+~?!WRB5(Vl5)&-0c o;I={;SR91ncOuL`vG9@>DdxlLLXZ=PZo4DZPso12;(oX^0O`BwGXMYp diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410353 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410353 deleted file mode 100644 index 5fc02221c38e07e6bba4d8bae3a1d17d7ea56139..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6092 zcmd5<3piBi8$W}|wGc&FLbi~|tt2!?a!rUNmC{6uN^Vmdt;DdTTsQYzD=JC`tD>7r zl$~WU+HR_?fATLjOG?xK`_7!1|FMn7^r+|QeV%i^_nh-ye&74P-*?^*LD*z+@ZAx* zouz(s9bL90+%HNw^1Z2r^vhOhE$ik7`K8N&l+6C>tnJ13b3J4AH{PE)($M}xuASJ4 ztY+iaeN|#>95R<^A0HglCg1Cg6>;)&v#nQ3?3`IhDwj6&xtJZwxVYHU^9OHaHd>2}!F>bskc2kIh)+D+nt2+3!TxuQ$7Z^wm%z+I;b zesu_Jcb;#wM>WW;&g%(FZtII5Wi{^}d$sy)x=nmdsiKcfW6nDFbKZJqUY$=HP7^vK zT65oLba$$Y@~ZGQ=YgQ&Gig2U+er6T*1nIJQJ*++xpMY)AMxjR|M9%i5|~&N`^L82 zGicLD-G>>~CqQ1pKFq4Kcdo`@VzyY}(ms<*;bi5FHw>O!F;x&2Hr>fwT6>x}n98BC)iv4ghf$7G3b zRhM^72e#0-v z&_4vhg9Nd6&@Lna7xAYkGr4`X{8F=@AOr0aT-U9#fDa;yxuiocQp5t)+=1s2!W0WjAR0xak&TkbUAn@bS3-0N)`3CMZLKa z89D}(ASy42I(9-iFE1f~ScU2Ghjp;3%JcO7Btk<{0c(?u-Ze`xrhmq=j8)9fbVv6*Lg zXiF~3^Q{e!3NlTn54HLvoW-yPuYk zzICMbA*GSh-(-JJkK2Q|1iEyXDea=If0WJ9Ng+r}$XHhmFlsf!{~miS|JHxE=^C-V zC8e=DqZy+ObAg4u>V__>HiNroDkrDo+H7Z{pZj;$Gm`&&I@!A=Ko%x5CYX z>k%-#fRH?@^Q3gfa_ROFS0Wu@(~cu1OYs$^Lw=OOzBdV>K8(hQA zH$e-lQTE;gdN*8+PQ-I^p~bcVPH~g=$p})ogE@%x$~2%S%F%@*u3&L2S7M^tMg4<$ z@5dy^<$^y<-3?zE6VKZHMzBpKUhus0C348Kc0+vgm0OEOG$i`J3lVL4&ye`&%Xj_B7DbRr&q+Yg_(3fTJ1Zq~^f)7~FmWvB>qIrm z_U~2TJb+1#i#eZ|GQTn=o;CW7V4F(3;CXi(;Sz^qxgrzoGykqpsLMGsaQDDT&&_4b t=KOZeSwQzZ*mDxOUNMFTpmB5O!~O+#5Ax^OAK%OKd!GM{UY;|@{{g&}sdNAU diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410354 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410354 deleted file mode 100644 index 942e9e3aa1a1ebbaebf67bdd4a15022c9056e5b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4708 zcmZQzfPmT7b30c^@}E4(+u<~8_wDpMeMKi)Bp>aMb!I?@N?LSw7Q{vdMi70qDD!4gz<1AF_SuhKm41bN)=h%DHi_%~$7k6rv0-pfz>AB}nC6>p-EXaDZmq>TM;pC@fRU@y!hWa+inKQ=hF;>RLGUO;d@HNZ`rIs;7*vYK3n%p^^+L|d4xT-eYmhotM=2M_YyyH@@##%UKyx~0ur8}Z*fhp&0OeE3V-bdrb7#W@w9B0f*o3zL<#axOX3 zx@JpkwC|J$E3R6+^*(r%VYVqJ&@6}_78UIljBlTPc-xd~%L6z+OKNgCy~+P+F!Ruv zu0AQ*iNyHf$jfg9tN%sHuG+$TsrQ*ld*m($-ak`I#2wDPw_5Df&3 zU~_?fxXjg6SCVDall%4bzpRD1a}%R}pM9aSs4B}yxqPy}Ov0MU>v*rNHLH+Fuh|iF zJ)HaYq>LiRHZi@Zii}HBPCnoVng#ZQ;cG|c85p)g_GM^snbU(&ol4j zNz)0!pzu#&5D+`fz@YIDWIqtYLDHgghkzWA7-vCoft9hbiG?vl7N!nNr}zgxWh#&3 zJ67$fwBz1Y&y@KAhwuAYgjns9nDTjFvoBB!Q$T1?fR8IgGl)z-buGDK7GG)a)?fL0 zlcPA?PL)`^F3%9KFkYuMbMdv$V3jkbHGpZL8=!7=h|7K3_scom`_}g6O1?y)+k27U$Aq4<;@l#gJtiWw{n~Ido6i5k7uU7Ny-=3BWz#pn@)eU zNhhad`$Q8^!UX9fHjKdPUfNzRe-mJ<8O~Xk%(%l|)ArcpXI4ws9G@ZZ%7Nm88Cn*Ag(efqcR*F(d=Du< zpvE95ES4~W%3GKU;>=H(gX|`lUJ#ANe2^bt{-C8jl=uU~*+>FNOt??M`2@}b#SsWV z!x62{1<8TpkX*lG*pDQD#00wlL=f*b65S+qsYC`E?-=$X2_P{^b`v}dK{|=9ACUY3 zw-Ly|<`CCcnNeCBR`oEHE>J5H7rfhk>Y7HHm80owxkf_|e@R%_k(MV3)#nTh;vQu$ zKz;+&DHs5YJ5kdzQRY9VJWo>J9!mUy5iCdoNKANe!r~4lKw6$8&F>iYBMBfeVNM}4 zPZHrKt(8r%c*n38NdSpSvYSxyB+>0o67r<(frdTx#{cH(t`6vbQ`W=p@~2(aEJys^ zU+;=v>BgZype|1N4+KCq%rA^U?k}huDDF|}NrG({1_m*WHuYOT<3Q~gP#+1@{(%FS zB|rfrCR`d!d;AHcG+^)E1>i9D>6HsSXE6 zrAI=`%)%#L$E71WHmNy_l{oq_`ON;;)1sGr-)ir?-Y#f-V@so;z5@ur!W>=)5Yhi& zU|+v*4YUvP7ib16*d!={lrWK)a1~^wQ6k;sL1Q;zO{0UvZ76A!L^pxb0yW|gYZ`^c FJOGf3S9$;d diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410355 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410355 deleted file mode 100644 index 09230a1709e844319d636ea44049afdc603a2998..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6060 zcmZQzfB?Y_U3;d=RhBwUk(zOFZp1{r+w-n4?78RCChM_d!sNtCpeo_n)^j^oNb;XN z$=l&HYxnK+JAFkbS|lIsk9B50Rp9s0%%62X*Bz%Dp;O;V9p}3d{%_9BV;6!BOup(; zv|6?MQPXmeO-YN+&WG5@zzCwZ#tLlOU8~`D^?;T8(uZ3ooa7I04t19~5>UObiRF?_ zH&BTKYw^|othTr>S@ubdvFGFdPH0|viRqwy{hfn%?8|R^%*mb%qOHcf54LSyo&s_)^YIG@ zZ@d7pAmCIHkWOLn@pb^wO9E?nZbY&Q7CA1_JG3d3mtppd_Fqow3E$aj9~=ptGHW`| zZ2pH^yXDmvn*3a+e=6bGma_Jhf3}qWKWCvkzu;z)d3cY8iB9j&PYfyl{-y@SG;qnD zo|D+3>@fRU@y!hWa+inKQ=hF;>RLGUO;d@HNZ`rIs;7*vYK3JS(7#NPc{8q5~U!?4+Exea{pP95r?sDM$GqptAA&z@F zv&P{M1sL+pk|q ze!KkZT+R(5CO#7^!-S^Swmi%4T-xZXeQpO+>z*&yey#%f73|-6avqL-{49kl-~O=a zzx9COeWQ4&ndf?~O{MqFUW{o70jf)35N!du0PaU18y$fC4iofGcR8!AJb&tGt?6fG zbI+Ul&}}ovlU+SLhu)nmw%%LM0#au^>l92mBh(&;%&Xzs>{u(UbWeRWEx$f(!i)KZ zGw-fi__k_t^_+*Tr>?)1yTr93`BCti`>cO5Qp&Tf6NF#Me!n1ex_0Kqnc+U5a0UA* z#Xs;VQ+XWUv1(7H9rvz!rpymGeBaL^#A=_!l+XK`eZg_az_^ux>H8d@9u&6&^W;vT z7|Y%{Z{;@a_geCB9?wjDlaw#6N7%mHH=X`ylTJ>__K7B`P<>#%1nq;`@zVBk`I`V+ z&2Y}TWX2u#nzqL#KeJl8=J*VOC+F`k%eVn@zhj7}Ul5Q11L>!(C0ESiEA8F-D_?JN z6o=cX5{uX683Go@>$GMrzV;cUj?qvTrkoM%KVbT}+$D0y$c}4b*LfMMTMt5an66&G zepP~tz?q6AimZXR9~a%ZdpP=M!Zf8nb=U7bY<~8x*s0}a(J9NHZ?ld#v1IT84Frd! znzGqPn@JB&R%&0%pV*SSm@&AozTRJ8uXyL4YfT05&!PFj2;>ZyBhc6kDND7#20XIU zI<$ON%tT?I(BA3Ys&8xLBemOe<5iOO-U8`k`t_j!L<0dM*j%6=6dL^5FTP-^YkXS(@}BwmyyWjGHHGF8fyYuOJug_^ ze!q$vXcpKHhOZr&XKYYBGmS+x`<2SK6i#kurA{BEJkPw7Cru{^gEC?YgMip+1_q7) zAp3zB4w4p~I|k%{#5fCz3#^QdO)Nm31p=5lFik`nU&X$?>v zj8L~aYztoeVWvg*->WbG82?|fb%S`5mTWrL`qm#Ii&Cx~R+i!R^SyQctX!zIxcf@) zrxnR{+A9_sGt6Rr$lacHs4ou`F04xLU#QQn`ukohe6#u~f#99SJ|^v-m*%|bob-mx znrT8j)J||I4`jpq3d&?V-gVc|8{+(t=wp~new#E}w*;4ndJ z55eLWBnLK&h`N>ddKH#H5cMmvdqL@%+<2m0m{8^>WdBhso*2Sc|KBi~VVgxs|I9z% z?3+K&7QP_x$?%Q+5oh}Y7iMPNg9bBtIRXoP5Dm>2;5G(WoQO7wxJMbV*$HWvAe#kd zqj(e|i;~8PGynM<63hqr0qPG#x}kwRl=uT9SdavenDF34Pshml5xwsMl0(TeB>El0 zek1`TCK+x+$}_~ciRX?iEZ#BfMG`<_lI$i>odqvjh;Az*>4Dn_WMFg15zh>_V^6DI zU#T{bo$;oHi^W)|yISvR2u2|HA5;#Omf>|f5p5_2_Vo)r zpzSD-Ijm5#z!Z`@k(h85xY8Qfeq41sac)}hgvM?Hxg8c>@OT|0ZbK{E6t#^ zKMD3#fM&^_1$Nz#+N@CX!4wutP{NNm^HYH32ck_(z!hMP> zFQcaekY0>>gG9e$*pDQD#3aLQNaZatZi4n}K;;#Ny+{H`Op@J%Qg0C5r$+Jz+(vAU z1d0i7VU(F=eA3|BmBdZ;L3jS1ySMk^)G1fOp5_WgtoWd-4AqaV-uMNTgO!8udV`35 zv6x1idKoa-K;tp9f#&c+%>q+M0fxkctH71k@YWkdx=Dz}Zo-=P2Z`HI$_oC!`M!j@X7Mj!SSl#94w)@<@J8hF^`YjC?RXYEm zukx*^&imxtF=pRH2rS~&GhQ;CsC;K|9Vr;M*^g?A}=JZ6u6ybaSthJ1E~%1HU#NoNLi}=HQEO5E9fvZRL#9oVW^?k+y3DYge_ZxG%Y25E@)CK&sNGk2 za%Si+KDz1dGut%(KBnZ<(o4=+cKKP^0&C4VRBrk30?h*Z*YLF?^NbCOXQr{JX1`MT zmcq&HtkmhFl;@du@}%hmVUQzJ7zD&lGcag^?FSJskhJLB86X?vZ_a|^0xM%<6LV9D zBseUfattZ{flryrB2X&3YEZ zv@^HQ_*4>Kl)RM*l8*zt{Tw zDwoN3*3bNN>MJ|YEO5AVO?w?;K5_D0=M};UAro$U3UetfNnSKZFvscYgC%V~z!*^% zU=a4pU|jOYGNQ?s%E`}xspkRTi0n;ySFPFawu+ zZ1OX!rE8AQ5O{L_{<4f4K=n+HA-<78Kn4sD6DAS`QVme`j1YG+ICQ-`C~zRW<86|g zh>70DEx&nIWm(q!-fYdhsFmMl&&?-G8zW2HRw{|>Gfrm^zVk+mu_f4li+N6_HvVEdSDpVg>FG2gDb`Teqo_?f;C8MD(*zF)ULDQ)NyT;s<@70g@ zb+#{*Z21>FOF!iL(huhhbEkamwSRT@b4JUxyR6mq=FXVy4eh*ZwN!VyGE z_?Bq<7iAl2M}~$+6nncTXSrL1MV8yzg4_tiAONN(FDlwC7~eko@U|(}mIrWtmek~O zdXxXtVCJDSU42rr6G7@=We`EP0NotI{RC_{NFUgJ3=9rsCl_*x1buCr@X6 ztS^;v_1b4Qgav)lH&nN(v@)+aV`Baw?c}z+_{Gl)17Q)6@*fC5c0(P(2;}~PvO(d= z3@nq4p?qS>8!?SGbs?Z}ptL#%s1H;g!U4<@pa2pRE)9-9I1gku2te%zrt|qwIYv-j z31t)MCbe}mb`!|$u<#meZlff;K;;cJ;t(7rNbNFk^aaiN{`%Izb$wFo+3B7S>kZYa zf3_XG;eN{fllI<)vK$YgaSUz|0okxL1EWFGurLR;8^C~wJO`=YAZ-npHaLxJI8+cN z{D?GP2HKW^n+s!LF&}H%p@BV=_yfb)NCHSqm@gq^F`S3U%joFK`=B;13?PRaSd54^GK18m5?I2KMy}oEqxA<|6^Gy)U8xOGSjo5g5c}e6r3!#}d{9_3^;;f@q|K viNu7fz?DY9_5WT;A%FelPY88mhi)-*au+(t=wfyRTV5rZ-4AbM-8z^2``8h%#~Sh+8KxOKuw{_y5dcbOvr)%%)QF4=Sg zl{k1ii=>tZ?=wFoz4v}{jMw4HTjItYzIwUY#W5Qq<6NHPtrER|Z;J2ByBkX%%}$6} zA#*LH*;szv#P__v_XZFC4s+ z17bnIsUjeq!r>2I9oYWJ(v(-L05;|qpbe`G# z54U#9t1mS9xlaF7!m}-9?JNImDgS@YLU(?_%_Q^i9t{(n-k+ZsQvUr-4T@>tl07{q zu|?To_O;@h8T{og53i>_Tcy;saO#_;5+jkolap0X8DG^3?^5!3%pU!C8^lcv420qe zsE!4QnLz3dUpq3-*r0f38jEW7E0u34oZQYzojyu=o_QxvnobZl1S&~k5D+`fz@Q0= zGjP0t^npOqqH`C46iAG-pt!)w*x1AzqyY$E>cDi0f8bN5@;JU@)t*W_?p^gvnICZY zzMn;i)jo+SpZ7KU0@X7Gga!rpxPtY9iS$#~k}GEMmG*A^m9IBBio@+xiN)*k3;_${ zby_nQU;7MF#FP{T)4&LItHZWuv%;O~*DU+S`I+ZDliuE5^?c*4<%S#Me@;F3{)+O{ zhc9&^AIop$a9`vR;jHszy;h^-N+!mm)vYZ#E9XybVFeirGBjnW_Sb+%c3Ov)&x)BS z>=W8My<7EdjeMkbdv3f+(%xGPjBN{mX~P((6xpv5=5EPZk(s_xsjluW0VNR`kp^ZN z>5jIxXzCc$l+8ZcOnPv#Qu|u|#FpH}jKO{N_5K2T#XI+0YbuC;4pJZD4GB$xZUMSE zg!>6l3m7nh-3QD&XR`exx|#Iuo!UFON!it)et%Q!*?-&BKF%qSbQgWxbL^$qh27bw z7nyBQ(EG(;?&@~!LH(x#ys2^puktVJaw@U|O#_ET*R24j=XnxhLQmEUW(;`%5WGS@Z7wAAT_@Ql0s z=L{d7fTj-vp#9)5gt-GsgQ-8emrlPX_s($c$Gi)!zv{ncUSmAJQX=z#h0{lGVaI7I zAVsogQ(;;d!R7+vb+@8{$(&x9lgBuh&CWA9SJ8TB@4L?L3jZP|2rrMGwkK+J|5~0) za^_FAoU-Zs@8dIj^%fDa{J!4Hll3S&wyzeU)yHC zalEv1?fS3k-n-6;e}h_@@*fC*Y*?H!0=fU7av*;(1M`3hlut}q!oa?MK?Afr0ciu} zH#mS<0u(@E!ljYJ5hTbAmVw$2OlM1=Dj7j#Hk3`Qn`CJ0CXm}<;WgOYMoD;q;)xn@ z2o4jZ_5nEhR0LV)g?BstZr^_3|Hr$DvvY$3?YQr98@PzhD3c3M+z*Z86etZ#GcXz? z3=4BmISmFxl%)(zzdkfT%XXMHIE`#LR1hWnh%{e@1oN?`9U9m}i9axc1xWyj2@gh) zpO678FQcaekX~3Eg31}NSyZk&A@10?XpbJSCWF}l5d_)?DNAT!FQm@KZZAWO&+TXf zkCXd?B#T-No)%s|^HqDXfd3CSF8f`pM6X<&0(Bp@^7$834msSwLWJva25}jmtPE&f zz5%F-2Wl3WLW)QvCR_!sI0e@axXNcD-NZs;H-X#^3om&2JV@LIOM~EmCeclx_82wd z5ItXl-SYL|!(~Tm6<@~8@7YrpcK72YhDnUc9c2%~#A-RF&5yVTRs`xlKme{Z18PG+ zyA2Es1lv^%4B}cVo8|!ZfZA3VW+Dk7F`+Ji#4(%$WWdTDu>HU^Iu$C366Qp@$%4ji z!kR`0iQ6a%FZ6N)IZ{c9L-aHX(hG`TQ2K)BX%fSWc5WllO+0sGVd;xjZelTg=fC0RZVSIROC-gDdYHOR<`2XOAofm3U_A?jW zZPPnz)E@`3DQVH!br2gF7(w(3m9r9i=9aSgYR-y|UbDpd@G5e8UluuS^=_a3;v?J3-b!)IT-ove>hzEQ7hPwHmwUftv1jA?3MSD5j9V7V zznxS$yWJq;-A#|+vrM0>y3E+ttmCkoX;8Z=an|Ga>Q8*lM1l)glRl>9KYA{&?3^0- zRA!c1-&9Gya`TA-9PG;XPC_BI)+G@u8VB6;9DIga!AHQ($ z?jH~f0!|eH=@bSZZwC;)B(R3(MkK3Xk>e7*Lz_Z*8D`ID|K+5f@SUyp!I97@v!?UR z=6|@gTV8#k$l#E|muZ)#9X1DEXS zIf*UG4zsTn-^}1IcX@a{_1P+=u7y+IG?f^M1fHC%ddm2!R(O|^$7A;B$J-!oVqhQ? zS3q?vK+FVEKbcXGN7!TAhYP#3YCrvXFYzNM&(@dgmBFfxjMfW3k4iBxwk-gLfgwyi zNDmNz;}61QV3@|Y@n3#@abubN>2}|BwoDt22D!eMotHdw{ZrY?@s^4pb+TtuVagf7 z<^to^Alb#yiaq|ZLZgRAM6jti>skH-zdbKW*+_C+ymj}1G;>gQ^U^PgnXgVJg#P#W z7%LUkTCn8T8`mqFYpn&!y!n9!g8k4n?RALx#L0J^R|qGBOt|eS%%!v>dC?rf9H*-f zmbCdCWnfSjU=a4pU|8GwGSIpuo?cMq-UvF|0huf(V zi`V5D0v5*Wv}P{8_8Fv3qClzvs-6+zP6mg#X)AXgvD%u<|9r2KiLKqF{DSXW|4*z4 z&=Lwcon2ySvvSSm?Yul!OSjrgjoY_8#fM18Nsr*BrQtZ&%)Hx?8g;4t~Kd+GFR za_zk-~C5;l(tqs8jiw%+!6=f^4T z`ej0iQ0|;v#o4}pwkJpji#Xf^X<+*Gp#ek#0VCL4V7%UD_Bk0P>Z23yv^c_&YrP7nsA$rJ_wvC|9;njk-;xIJmnxvNky zPEfoW8=II}0tKLAa5}|5@F`Py9N)2OPo*9Au6m}-4>)|^&mzQXpTv~U`+eE3VgYKkoCiHl2U@%(>QyE&rQ1 zJl}s^8elPH@!C%^t%{1SZ5FcX$MbR$wi!;o_5I+ToC$THaADaNX6LrY_fzpkHqXs} zT)oBh6K6g7R3d6W&5nn=Vd-H|`UZiN|3CnwVPV1u@Fi(Tx9t?;GX9o85 z3uK^S4KkAzsufJZECF(mm~a)~^a$qx3sEo|YCkalt%S-kg34N$I^x_ke+P}-1j|pL z@EUAxqa?gQ{-Q=4g2M!vgkNa-4CKA6H{2}<}8XMV~Y?Q`} z@`dPn7s(%R8-WaL4tc+;U|rj+0H)Wqci8{(x(Mt}6Ak&d`km`hl};mTW#J8%Dl(~S$Zo-=P z2Z`HI$_oy1n3xvq^XICSONXSuCDm)Mug_98vL z9-17kasY9I2$lA$l4G>BXqiNDMF9xeciq5VX)6*&|Z9iA7##bgR%$qWmHPwi4ndFHDadg|)b@W=xZ{AKaG7a%_A3GW03=gR`Vm z;tBg&nfH|yoBdC}ZEPCnpZ}#rV1$$DVlih0Pmz$Fxuksj$vsbOg$4QjlR+fAw5FR2 z5g{DtvxJ-YE0evM4aBcnTj!-K|B)jj>#W41azQ4swBgtrIaq}_aj4X5%j1!pcy)bU zZryQzvA?=%Cd#!&o{QbbU6>5x;oBcM-)7@~%dep?FS6^_zSfZNEa;hSS=g^-{}B$Z zVln+Cc;+?5K9JLk`Mzj=T%LMorgYPp-oAL{aM8HfCwliIavZvKDYCmwRIimVS_HJZ zWZZq_?O|unUiD7m4#67Y302(KS9bGP5Y?%j5Z78ibymyDd5fJpQIbuc-6dc8nH(!WBs6B9c;yPY_EHTydqhH`|?U5gt( z>m|!=To)r!FV`+%aZX6***fcIWeb=fXr)@gdQ9*K5A^G&nat1goD=l?uG@oefz#N9qRbmNW)*yb~_ z2nfJG&g`J31{kmikclNOq0xI&tQw|M1KVqVf5gIfn@rfA73$k7yMG_hf!nIY)H2mU zoQcl)&-;jZD@f$d-H?qvdyZgTIMdm1-K9k9;^_BfTn`bYRf=h;eh6_Fb%gjjcAj#o z((=xa#`BF~Lbd!sEe{yKmkf?K_vq57MPuR?>H!hcZH`tksa%&WsdjG{kxaJZHVTlU zWIn8(sr5_J!Fzr1&fA_;E#=4 zEHuaZ4*L^V*}Wr6XOBzASg~l=dnt|iI&mt=6-ZpU-Z2TZ@OD;twn1#Xv(<**PPAo+^3}eR*y?9UKqlKrNZaJE=(T< zf^ZkeE80U4GpvR))ssa`2Ry8KgYrXr^j{rd<lGo;AN#&ld26MmJes_?Y_!KHm ztCX%mRKXVx!2q9)_1RgMnkw)@uQ> z{guM!084kVPn7|BmQ(z%W=!OUVCueP=9zWOU85d@9no8EHA@U0K1 z?{2vrEFr?uDomVIeniTjie)f#wq~0gW(015&vWr(rixK9Pc*W)Y)voq=yI(WO1Do- z+H_RCy)QjXAI_c_C&YEY3Bs9!J7^Jh_+Dy6=U4!jcgp`0)E3i0`Vo~@-*F=qaSPT{ z_Be{FxXPa~LxhaH+62zQ=H5)FE?6J0W@=z*0t;B9hsXTxTTY|;xCNXLkx9(Y+3zx& z=0G>30NI@7vw0S3+&Gcj;lp8}(L4FOYkyjAM2>j^E^UYI<0)@-N2hSR@tKIOx9^bSDtT>ErZ?)`(Q4mTCI4KbkfZY5uB3dz<5bReB{U{-tHCn1R&*Na zKwcSOo`bq0ZAG5IS^`ZD5UmYrige2a!GZe~)1l8lDd{u(gEe65Sj#wHvyP9_LNh@l zVp&??J9PwV1R9#hCC^ykH&DYbUHeDzX(nhy1OfO$_9Aukci27?)0T%`ThY3I6qja# zMx>&k7ZWvyz>@CsjAk9wh_J96kO?1+=wfzbcdOBAg&nLr{JV1PY~Z$edkp48R`b?X9MaB>98R1fJUThEUgcAXZ`ItLMNs@Ym5nC z$MQuzN4^nki_VeH!~~v$SEGhY&k>~PQIW@N2HLh8w+tQjvuPWa_F?BT=@F2ri>oVA zb0MpEq0Cs0qx0x*Sk9>&rQ`o9w5~9Pg8pX(_DrZRq@y7wjY!o1`m~KMj?#(Abd50q z>{!029Q{VHE#l~BVgfZ-jT$b?(Qb|CF`VJy^Ej7#Dg~B&Evip^-gK*tWm8I$gPM$*D2ALZw|ocR}%nlWjP)2gq{TSHY8 z_iBra2!U)$T6A^?#6|{25WO{4VAJke4Zo`gtlXDA+&bYTe|U4KyUdY*>U~Wtmu$L$ zN*q4WE7FN1nemo0%yZp(CT`SeCs!r@XpBP(RSpHIIGT)DR z#`~Ru?sHmf|18gaS0qKY_wm2YYX7^x7x#U_T+1HA1X7HE0JiMOzY?V^i!l`eXN{mDTPfk`nWqegDyi3XBF?;mmZ4fsxFc69> zpgI;HW&)`%(3sd78~lIS0!emfwlAfs))y3Gx|$yd#Y)dO^VaWZ8Bht(=V2!q7!+3k z+2D8s=>q{^d|raE;NrYMK4YjiM3h7I#f}C^*@UgaG6Ic!Wj+oxM$m$At(Qf0^ z@dIKz*i9fmlHwkc?SO`nL+)Dx!R4ODmA@mEAD(&C)63(KP;R-|=IGRf;|cn)-o4t} znN6a0M<_m9v#K`e{ES^1yY+W@Zn+`Cf8k7vPSsUTpgY0wVffmSdBz6CGt*d9vtOxv zOX1{pR_gRo%Ja-SdD3)(upv-g3WI>yX$A&OP#mJg$GHbkG0uYG0xM%<6H_Cg08|W4 zr}zgxWh#&3J67$fwBz1Y&y@KAhwuAYgjns9nDTjFvoBB~Q$T1?fR8Ik3k0N}x|Uoq zi?6hI>#uyh$x$3`r%EhdmuCoA7_ZZsx%k>=u&No;8lcJ

B21UADOKR@L&*AKHsf z^D*2Ez4l_uw{HeJ)#h=2<(QW=`)_HK_Q6;2Hx|9fxx{|@&C;8HTYXPdFEHR*v?e@c z&Y>oFxJ={Q_%FY{xUtOsbi405Tc!<1gIwRs&P$%T{;BNccuPeF#<*a3YwRE7U_Zlm&F#l?!`dUYHvH80w8=U1lJk4};w92s zCN6aT+S(DhxcKWonIp9yCI;jfwDeCXekRMr!3{JK?EXiE(PH&$TW|Zk^WzkE{W76M zD0j}T;%whP+Y_XNMI7!S`4^T3K(s_|sCikkeq>}xsDGe^M{;ILxJQIbpsg*)Z&25Q z=|8)dPQNDi&T#I>ybG?s>c3`QV?4i7BJ+WT(?@S%$7w1c^{}uY=oX-xL%5$njb~s4 zyAK!^3zN-fuT`Rf0G3f;fZ|7}7$`iMp=kpwM1+4Bn0|d|K-L2_3rxW*K@wvG)e|s2k><;g zU_QtXFn`d}9!mUy5iCdoNK9BLLDDZ|#QfQBPlTLI>GbD#>aSyWEHV5^bxG_reP zVL}UgA^8STmLS{9aA>NC!-aO_Pch4)mAI3S)SYa_j&=u(HLnT zRF1&_a=3xTh$sgcq%M`f(k6;~Kn5TQATeRq;fzyIyn)&ao1rRUVG8CF=ceKv(ENg7 zFOmQf6KWG`eE<@Kr89IlVa;QM#BG#>7sy{I04b1=m~bWN>S5spE_cxKC9)jYEF!`S zUat_WV_{ChoZspW_XEFsmolz@V4ap~e(c4sFNJ5hS8RfsnDQS8fNYpuyg=?hs2nJ~K;f+e zi0DIr+{8g+H-X#^ z3om&393*a|B)mZVKS(^l10TvjiB7l}t~kUr^>wD(xFoM{F371&6nTo zet6$PX1NdA~TJm*DEMt gPMn+OeW0Iqp-9A0K%7{w*UYD diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410361 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410361 deleted file mode 100644 index 198df6f33e92c1e7785c7c42754189c79cd012c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3844 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 Tp>bQF`O+Jhx|>NbA09XWrOuMQ diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410365 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410365 deleted file mode 100644 index e989965ff7636746574cc2e6a5810dc486c57550..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5000 zcmZQzfPl5^fz>IRsZCo89}5bJH}BeQUU;Lt=GcOd-5wo1YtKIcsuE_Kv%+_WdyUM` zl!*;uH(G3qnbXfLX)(*2e(+*c(ImGOt>>nu1#0E>EHB?&x_|dcK4aIA1K}a3zIpE3 z>zL(vU^U35q(x`1Kx|}S1kqQEGH)gYeD};{pZ(~CsgT+G|1U1j(PP`cdZUxP_@8tc zpb`h2Z89t$UmJaJ6mK;6sG?N;-GAMl$SEhx*i^1A3A8)*q{9AJj`rK!ST+UME8@H< zf(xy-uIM@Z<;p+rgipUxPcna|xp*z3eW|Db$kA{g(@6S&RDgXYa2E{aR$)28* z*rMz(`&#kM4E}PLhu2e|ty1b*IQ30aiIGU)$;qmxjIU~icPV*1W{-Zn4dNyS210QK zRL26uOd$1!uN|3ZY*0KijYT#4mCCmiPHtzVP9LQ_&%Bc-O(zH&0+pmN2#B3#V9?|Q zvcd5N(gy-bi_ZN4QXnzTg5m-zV<4~uNg&jL)u;FeK4mJ8<2zREskGzXRnL_90f+DV zS%g^albG^(U$ZYzJySqvP=JpsSTC4JKXom+VisR%@77=WdXu9#+)kBPye`iWurOYy zHFNQ`&tOF}rZqryFhbqxaMS0YRfD#x{I*k#dv-lpE|`2S>$Py*SH|tjFGkzcoA0r{ z^x%=Q-%rho0D;I|%#3eSxA8GKp6i|L(fw3EoYjUGXdXCR2)dcEZ2{1mTN#+X&jac~ z3zxHRfnqFo{G7#14*1=Ba`B?1UX^r?OtFe>%g0RjOS@{k+!SUwK=lzDMqqU>Z7-L< z39!`+=d4R+++nY2du;MEtEFp>&k%TW{{FIz8$dIe978-^f`AMdAR;U!ifV4blruu( z#6dXI)cC|C;Ya_R731u$^Zow9yFxHgQ9g6u+Urw!ue7$T@m_k*UUAxMg-+AZ{Ssvf zQ%+S{sjiZcQ9RXgw~W1v4`?7bEKfuxY^o1kx;cFFJc*t28(z+8&uDsaar%u%k$b#s zEZ8j>Kw&A`Y7J8lbqL76U_TSo4@~kPwISX{V6Be|qs8jiw%+!6=f^4T`ej0iQ0|;v z#o4}pwkJpji#Xf^DiZf7djVDp(g$_}u&lZBY=6MR{wv8k2Zg^>-2RYRJ0;jEP(k74 zu|w+)-7B3PbLvNafNE-Lce2vK!_IC>zWts2}cMQ1%37(52d610LCF z9a=ssW}>i9Xz%oH)webBk=pIK@hVAsK@p4MU$7g1{ymlCY}a4#o8|uM?vFgzel6N? zUHNiqf61NC_LeF=F7jeN`R(f~IBx#zedseMXv9`kku^T zuAYbrz9Qsz%&7Zn-Xl!~kt?5GWLSqBDL!@iwvCd-V~`>sNcj&0KpN&>Mj-bWSO$_t zn1S(c0_8Ih%zF$BVj68~>ww0A^50ybK2W}e1DGX10VF0|8k{EKJYb;?W<%`<)=^8K za*Uv|AEu5-H+j+6O(3^}FetnRo7*S}FHjjujW`5{2~s-)9DPAoQvKcUJ~nD~3yF_w z)_7diwzHho?Z5?(uP3<wYCszeEMBHd&`V>e+UQtCUHqhR#_vU^d=5+dvcrE6FkqFtCEm2YIY2_^p^c@~KY3lf}p z4LzP1UeC=>{%4=$)*toFp%to;@ykx diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410366 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410366 deleted file mode 100644 index 9a1eb601e6eaa7c04c6662fa3cf0e5c48d7895c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4996 zcmZQzfPi{WB!mRC9N-ObX4)n>T;%yX%#QfvSYpvIkbDXr?x8 zEqp8}B;LGhw|U`>@|t4{K6ZO_^sGJq#Kf)dn$@|0N6`i94+2)1O-|&|S4hwC~}jw#J;l4Xcfq-ius+87lbM zZvBLGw=St7pLLVxO-amX{J`p$vA(qRaL9FA9pmE_O)+y%^te0`{%erBb;fLzRc{KB!i z7!V5rP89>`6b2t}2N1m^u!iSGB&%SN;}X3?n?iXRX3uE<<)ohQovrr4kFSe`oyfr0wg4CghCrn( zAoWlHia&5164cMYzynen;teu_f#Jx@Zw0IWMar()!h5OrnMr%(E(hK}Q%l4h;<%SH zYaA|ws5JtseN-4NR=>9Ow$D31PI1>S6H0_~=j(_@MiW`Wz zKnx_n2zEa(4JjLZ7JvWQ{;>V>3IW%o#rs^(yWig$d(~I6nDNcLRIjTQixle{5|5tO z-?VU|!LeJK&3^qpA2d&L1otk#`_W-NKhR8YSmm4fsfb_HkiY&VQ%?TTEuL9RV~+|R z$Sj``XFtb3B0m8dRyHv8P`ALtilBZ51~#A`U|2!?|0{j!bE_qqvG?Da{dh2u+kYFg zrJeOg<_XvJCau|*>6iypEACPD0%{EdBiIc<|0Z6sd~UG+$@;d%9~b1S1bUUZZcp_4 zYH0R4bq5kMh8^LQZUFl?#Xs;V zQ+XWUv1(7H9rvz!rpymGeBaL^#A=_!l+XK`eZl@^VBE^U^nE_a-7trMXkcFd45V1@ z_&JN29PqpMd7&Rx_Nl zE}3zMy{7H4$%Q9{N&17;6@pK6SGGHM6)V1V_S$w6vTYu&2O^)Jl zJ5^%wx;#U`!g!t5%*EG0Zj~sixdl_s2=*T^EMMronW3eS&Hd`{beRc$>WU(JLbsGM zEMZ^z?$etmf`#$+;YPnW`2OCXko@DN(}iwdlPFGwyCOf@)s}qF8S)ofScKrQzG)2U`ltXAl4jM^L^&0Yv0Apn7nbM6>+H z)>qyDv;>sbKzR-sfYJ;zu&l6z2@>O8sY}Hn(DDUdCc*T>0s_cKV!~u0X%xu`3l@gpxF9CY4`8_gD>K0UCBm)n`jMFS z0W?@)^(1nb!qPdt>;>BcZLdI`1*bq^U;^Zk;1;6WQ%oV;PZ$_BF507a6l@=bVL*|+ z$aXV8>k@b%tX`Xvsm7kO?5gq12B{NkgjfQ#@>f_Ct(kE~Z%($I^(2VvG3rTBdj$qy zWvVSqfQU91gY4OqIl%A-wc9}MLvbS#2Z;$Y9cTFkwjWr2U4g2Er8O{@C^wzH`-jGE z0)-VUyx?`vAaNTd;RW&&N?ajvkeJYzL94HTqWJ0{WI3=|M1&W-ydt7K4|5c@@(NT& zkQ-053lqxR1acP~AVm%m6E2OS7AT4w7sz7^3_8z#+Huc5cIndUYd>dM>V(hjaClhv zB8~gzkId@49jsTuCIZ{r|A7F=hS|jkf}^4ht`M`Wz%~Ln%i{bQ7pgON}@LhY3 diff --git a/exp/lighthorizon/index/cmd/testdata/ledgers/1410367 b/exp/lighthorizon/index/cmd/testdata/ledgers/1410367 deleted file mode 100644 index 68ee1497fa693d5940f67a5470fabe7b2a78f7bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6884 zcmZQzfB?<8egX{V-`skpTvUE*$DW{A_hqRyFK@YJ8aOZYI?i7PR3-fG*9MK$Ck-bx z-A+vTw10*~n`-V(mPw&mdGqGaeRsX`usxul(gvVJ&27Aj39c2%2|m$b4%HLHD^UfuUTS!c$L0UriG|&kN)hfr*l6T z1C=;%SAUqpKKshM*u*a(e0i&8H(lG8^uu&}ocFqaZieaMR~E`!Ghd%}=0ej_=Lw!0 zrA%x#OzC+TVt7#V+I#V}tWQ`!NWK5URH-|6O^w#qsQt&Y{;+ku+q&FcUjM>2>7=h> zdc02gdoOL-r+M#$b-FA^ai5>4>V)MX)1&X)xu4V5>#oNj+G@}HVB6;9DIga!AHQ&1 zY7U460jElVbP9uyw*!b?5?I4?Ba&6H$Z?6@p-rK@46|pn|8i1K_|8`Q;7I6{S<`uD z^FQ3$Ew8@NJ!O1VE4)j|<1u^m<82T(F)$E{ zE1)_SAZ7xoPw@|Y%2Xc5cdXh|X~(^*o+tCG%&k%TW{{FIz8$k1z978-^f`AMd zNI!KgxndSyY46rw`FfM1INVN^SiCOJ5U?;_r!{l&wa-9x5=Aw)V9FW6{sX45PIJXL zOT)R}=QmDXym8uRao>qQr%mrH)zH#7Tj#lbm!XK>kJ{F@#bL_-*DJZZwaWA@5{!Py zw8n?Kbk~oQ6Ixh-27<%#&+etuugSeLocl5Fg6psPubI~v&##ood|=`9(OcMYnhH29 zMO#gQ>OtWT1MsjRsGos>2dIfL#M=n0_fcWASpC}8+dl97IK^GROehh`owKVr+xO4* z1nFQA2UuQXVEy_Kq@Ejyxxg9`1S8m8z%Y0yv-W(MNs;A-QqCB=dy96z?SJJTX^<=y zcRS}#W7DcA=nowOSQiSJhIa|w0u^~ zL}8!M-s#<{Z)@ZuwcB&!Rg(6CA{!oFztX2Zw_2hZd;hK3j|UUE{kJh&+F5U8o^V}n z(wcplj(H#h@r4!G{lKtVw>G`|?)Bw8W}+-Y=alR{s;PkSmQU7{WXLl5X&7Bl}rMtd+ zc7LzbjBVOo&gpYDF*(?Qfk9mW==}2x+|?35J>dKUq`?51_dsHt1;qtc#>Qp_kPv~Z z1FI)4AB6_HK+OeFMC2m|h8fcupjsFqZe?(o)idkwj)aUUcUj+**l9mH+O|mOxH^Mv zj_yP2X@9)$$nAK-ap!P)(bYR5`;<1`KYv0^Ytue|`)$XMulm^Lzi~ULj$nx^-R9jM z`G)nw?3zSFHA3phFOBjgsT9@C7cJc8w8;C1LNr?RE`l;mq6J> zx~XCojok!tJ1o2go7*S}uLVGVQ6mn)VS?0d0Y~3)|1z!Oe+_|p5|+K66(sI$$-b=3 z=ECH7T~a-p~qV`>g$|`8c&r|Hyqg*)_m&Mvf8OjqAkRfIU;*j zzmWvS7Z8Bj7+?U4JCrmDk|Cl^22^#b1V{keTC{1GvGtWV0L=%rUqS6yWB{wbtYCt~ zxL4{@aR{(J2DK+Z^)*WQ2nz_HI1&?PI;vWzeo%c6wjY=ek3dzz;vdW<&P_fpGnfPGcw|fB74DhL;LnnXCbJ@dy#K)vQ4-Xew)ma zd+r>+`bbfg)6<=&WRHs|*Kb+Z2~kP7o+M)Y251y`%n&{%LF^a~DfJ&Q?ts>Rpu9?# z`j0p_f$Kk7x(RFjH%QzD%M;+_MxvW&SH}Q{#K36;sje9`Zllaic= 0; i-- { - if beginOp, ok := operations[i].Body.GetBeginSponsoringFutureReservesOp(); ok && - beginOp.SponsoredId.Address() == sponsoree { - participants = append(participants, beginOp.SponsoredId.Address()) - } - } - } - - case xdr.OperationTypeRevokeSponsorship: - op := operation.Body.MustRevokeSponsorshipOp() - switch op.Type { - case xdr.RevokeSponsorshipTypeRevokeSponsorshipLedgerEntry: - participants = append(participants, getLedgerKeyParticipants(*op.LedgerKey)...) - - case xdr.RevokeSponsorshipTypeRevokeSponsorshipSigner: - participants = append(participants, op.Signer.AccountId.Address()) - // We don't add signer as a participant because a signer can be - // arbitrary account. This can spam successful operations - // history of any account. - } - - case xdr.OperationTypeClawback: - op := operation.Body.MustClawbackOp() - participants = append(participants, op.From.ToAccountId().Address()) - - case xdr.OperationTypeSetTrustLineFlags: - op := operation.Body.MustSetTrustLineFlagsOp() - participants = append(participants, op.Trustor.Address()) - - // for the following, the only direct participant is the source_account - case xdr.OperationTypeManageBuyOffer: - case xdr.OperationTypeManageSellOffer: - case xdr.OperationTypeCreatePassiveSellOffer: - case xdr.OperationTypeSetOptions: - case xdr.OperationTypeChangeTrust: - case xdr.OperationTypeInflation: - case xdr.OperationTypeManageData: - case xdr.OperationTypeBumpSequence: - case xdr.OperationTypeClaimClaimableBalance: - case xdr.OperationTypeClawbackClaimableBalance: - case xdr.OperationTypeLiquidityPoolDeposit: - case xdr.OperationTypeLiquidityPoolWithdraw: - - default: - return nil, fmt.Errorf("unknown operation type: %s", operation.Body.Type) - } - return participants, nil -} - -// getLedgerKeyParticipants returns a list of accounts that are considered -// "participants" in a particular ledger entry. -// -// This list will have zero or one element, making it easy to expand via `...`. -func getLedgerKeyParticipants(ledgerKey xdr.LedgerKey) []string { - switch ledgerKey.Type { - case xdr.LedgerEntryTypeAccount: - return []string{ledgerKey.Account.AccountId.Address()} - case xdr.LedgerEntryTypeData: - return []string{ledgerKey.Data.AccountId.Address()} - case xdr.LedgerEntryTypeOffer: - return []string{ledgerKey.Offer.SellerId.Address()} - case xdr.LedgerEntryTypeTrustline: - return []string{ledgerKey.TrustLine.AccountId.Address()} - case xdr.LedgerEntryTypeClaimableBalance: - // nothing to do - } - return []string{} -} - -func getIndex(ledger xdr.LedgerCloseMeta, mode AccountIndexMode) uint32 { - switch mode { - case ByCheckpoint: - return GetCheckpointNumber(ledger.LedgerSequence()) - case ByLedger: - return ledger.LedgerSequence() - default: - return 0 - } -} diff --git a/exp/lighthorizon/index/store.go b/exp/lighthorizon/index/store.go deleted file mode 100644 index de5f4f6f07..0000000000 --- a/exp/lighthorizon/index/store.go +++ /dev/null @@ -1,377 +0,0 @@ -package index - -import ( - "encoding/binary" - "encoding/hex" - "io" - "os" - "sync" - "time" - - "github.com/prometheus/client_golang/prometheus" - backend "github.com/stellar/go/exp/lighthorizon/index/backend" - types "github.com/stellar/go/exp/lighthorizon/index/types" - "github.com/stellar/go/support/log" -) - -type Store interface { - NextActive(account, index string, afterCheckpoint uint32) (uint32, error) - TransactionTOID(hash [32]byte) (int64, error) - - AddTransactionToIndexes(txnTOID int64, hash [32]byte) error - AddParticipantsToIndexes(checkpoint uint32, index string, participants []string) error - AddParticipantsToIndexesNoBackend(checkpoint uint32, index string, participants []string) error - AddParticipantToIndexesNoBackend(participant string, indexes types.NamedIndices) - - Flush() error - FlushAccounts() error - ClearMemory(bool) - - Read(account string) (types.NamedIndices, error) - ReadAccounts() ([]string, error) - ReadTransactions(prefix string) (*types.TrieIndex, error) - - MergeTransactions(prefix string, other *types.TrieIndex) error - - RegisterMetrics(registry *prometheus.Registry) -} - -type StoreConfig struct { - // init time config - // the base url for the store resource - URL string - // optional url path to append to the base url to realize the complete url - URLSubPath string - Workers uint32 - - // runtime config - ClearMemoryOnFlush bool - - // logging & metrics - Log *log.Entry // TODO: unused for now - Metrics *prometheus.Registry -} - -type store struct { - mutex sync.RWMutex - config StoreConfig - - // data - indexes map[string]types.NamedIndices - txIndexes map[string]*types.TrieIndex - backend backend.Backend - - // metrics - indexWorkingSet prometheus.Gauge - indexWorkingSetTime prometheus.Gauge // to check if the above takes too long lmao -} - -func NewStore(backend backend.Backend, config StoreConfig) (Store, error) { - result := &store{ - indexes: map[string]types.NamedIndices{}, - txIndexes: map[string]*types.TrieIndex{}, - backend: backend, - - config: config, - - indexWorkingSet: newHorizonLiteGauge("working_set", - "Approximately how much memory (kiB) are indices using?"), - indexWorkingSetTime: newHorizonLiteGauge("working_set_time", - "How long did it take (μs) to calculate the working set size?"), - } - result.RegisterMetrics(config.Metrics) - - return result, nil -} - -func (s *store) accounts() []string { - accounts := make([]string, 0, len(s.indexes)) - for account := range s.indexes { - accounts = append(accounts, account) - } - return accounts -} - -func (s *store) FlushAccounts() error { - s.mutex.Lock() - defer s.mutex.Unlock() - return s.backend.FlushAccounts(s.accounts()) -} - -func (s *store) Read(account string) (types.NamedIndices, error) { - return s.backend.Read(account) -} - -func (s *store) ReadAccounts() ([]string, error) { - return s.backend.ReadAccounts() -} - -func (s *store) ReadTransactions(prefix string) (*types.TrieIndex, error) { - return s.getCreateTrieIndex(prefix) -} - -func (s *store) MergeTransactions(prefix string, other *types.TrieIndex) error { - defer s.approximateWorkingSet() - - index, err := s.getCreateTrieIndex(prefix) - if err != nil { - return err - } - if err := index.Merge(other); err != nil { - return err - } - - s.mutex.Lock() - defer s.mutex.Unlock() - s.txIndexes[prefix] = index - return nil -} - -func (s *store) approximateWorkingSet() { - if s.config.Metrics == nil { - return - } - - start := time.Now() - approx := float64(0) - - for _, indices := range s.indexes { - firstIndexSize := 0 - for _, index := range indices { - firstIndexSize = index.Size() - break - } - - // There may be multiple indices for each account, but we can do a rough - // approximation for now by just assuming they're all around the same - // size. - approx += float64(len(indices) * firstIndexSize) - } - - for _, trie := range s.txIndexes { - // FIXME: Is this too slow? We probably want a TrieIndex.Size() method, - // but that's not trivial to determine for a trie. - trie.Iterate(func(key, value []byte) { - approx += float64(len(key) + len(value)) - }) - } - - s.indexWorkingSet.Set(approx / 1024) // kiB - s.indexWorkingSetTime.Set(float64(time.Since(start).Microseconds())) // μs -} - -func (s *store) Flush() error { - s.mutex.Lock() - defer s.mutex.Unlock() - defer s.approximateWorkingSet() - - if err := s.backend.Flush(s.indexes); err != nil { - return err - } - - if err := s.backend.FlushAccounts(s.accounts()); err != nil { - return err - } else if s.config.ClearMemoryOnFlush { - s.indexes = map[string]types.NamedIndices{} - } - - if err := s.backend.FlushTransactions(s.txIndexes); err != nil { - return err - } else if s.config.ClearMemoryOnFlush { - s.txIndexes = map[string]*types.TrieIndex{} - } - - return nil -} - -func (s *store) ClearMemory(doClear bool) { - s.config.ClearMemoryOnFlush = doClear -} - -func (s *store) AddTransactionToIndexes(txnTOID int64, hash [32]byte) error { - index, err := s.getCreateTrieIndex(hex.EncodeToString(hash[:1])) - if err != nil { - return err - } - - value := make([]byte, 8) - binary.BigEndian.PutUint64(value, uint64(txnTOID)) - - // We don't have to re-calculate the whole working set size for metrics - // since we're adding a known size. - if _, replaced := index.Upsert(hash[1:], value); !replaced { - s.indexWorkingSet.Add(float64(len(hash) - 1 + len(value))) - } - - return nil -} - -func (s *store) TransactionTOID(hash [32]byte) (int64, error) { - index, err := s.getCreateTrieIndex(hex.EncodeToString(hash[:1])) - if err != nil { - return 0, err - } - - value, ok := index.Get(hash[1:]) - if !ok { - return 0, io.EOF - } - return int64(binary.BigEndian.Uint64(value)), nil -} - -// AddParticipantsToIndexesNoBackend is a temp version of -// AddParticipantsToIndexes that skips backend downloads and it used in AWS -// Batch. Refactoring required to make it better. -func (s *store) AddParticipantsToIndexesNoBackend(checkpoint uint32, index string, participants []string) error { - s.mutex.Lock() - defer s.mutex.Unlock() - defer s.approximateWorkingSet() - - var err error - for _, participant := range participants { - if _, ok := s.indexes[participant]; !ok { - s.indexes[participant] = map[string]*types.BitmapIndex{} - } - - ind, ok := s.indexes[participant][index] - if !ok { - ind = &types.BitmapIndex{} - s.indexes[participant][index] = ind - } - - if innerErr := ind.SetActive(checkpoint); innerErr != nil { - err = innerErr - } - // don't break early, instead try to save as many participants as we can - } - - return err -} - -func (s *store) AddParticipantToIndexesNoBackend(participant string, indexes types.NamedIndices) { - s.mutex.Lock() - defer s.mutex.Unlock() - defer s.approximateWorkingSet() - - s.indexes[participant] = indexes -} - -func (s *store) AddParticipantsToIndexes(checkpoint uint32, index string, participants []string) error { - defer s.approximateWorkingSet() - - for _, participant := range participants { - ind, err := s.getCreateIndex(participant, index) - if err != nil { - return err - } - err = ind.SetActive(checkpoint) - if err != nil { - return err - } - } - return nil -} - -func (s *store) getCreateIndex(account, id string) (*types.BitmapIndex, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - defer s.approximateWorkingSet() - - // Check if we already have it loaded - accountIndexes, ok := s.indexes[account] - if !ok { - accountIndexes = types.NamedIndices{} - } - ind, ok := accountIndexes[id] - if ok { - return ind, nil - } - - // Check if index exists in backend - found, err := s.backend.Read(account) - if err == nil { - accountIndexes = found - } else if !os.IsNotExist(err) { - return nil, err - } - - ind, ok = accountIndexes[id] - if !ok { - // Not found anywhere, make a new one. - ind = &types.BitmapIndex{} - accountIndexes[id] = ind - } - - // We don't want to replace the entire index map in memory (even though we - // read all of it from disk), just the one we loaded from disk. Otherwise, - // we lose in-memory changes to unrelated indices. - if memoryIndices, ok := s.indexes[account]; ok { // account exists in-mem - if memoryIndex, ok2 := memoryIndices[id]; ok2 { // id exists in-mem - if memoryIndex != accountIndexes[id] { // not using in-mem already - memoryIndex.Merge(ind) - s.indexes[account][id] = memoryIndex - } - } - } else { - s.indexes[account] = accountIndexes - } - - return ind, nil -} - -func (s *store) NextActive(account, indexId string, afterCheckpoint uint32) (uint32, error) { - defer s.approximateWorkingSet() - - ind, err := s.getCreateIndex(account, indexId) - if err != nil { - return 0, err - } - return ind.NextActiveBit(afterCheckpoint) -} - -func (s *store) getCreateTrieIndex(prefix string) (*types.TrieIndex, error) { - s.mutex.Lock() - defer s.mutex.Unlock() - defer s.approximateWorkingSet() - - // Check if we already have it loaded - index, ok := s.txIndexes[prefix] - if ok { - return index, nil - } - - // Check if index exists in backend - found, err := s.backend.ReadTransactions(prefix) - if err == nil { - s.txIndexes[prefix] = found - } else if !os.IsNotExist(err) { - return nil, err - } - - index, ok = s.txIndexes[prefix] - if !ok { - // Not found anywhere, make a new one. - index = &types.TrieIndex{} - s.txIndexes[prefix] = index - } - - return index, nil -} - -func (s *store) RegisterMetrics(registry *prometheus.Registry) { - s.config.Metrics = registry - - if registry != nil { - registry.Register(s.indexWorkingSet) - registry.Register(s.indexWorkingSetTime) - } -} - -func newHorizonLiteGauge(name, help string) prometheus.Gauge { - return prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: "horizon_lite", - Subsystem: "index_store", - Name: name, - Help: help, - }) -} diff --git a/exp/lighthorizon/index/types/bitmap.go b/exp/lighthorizon/index/types/bitmap.go deleted file mode 100644 index 171115938b..0000000000 --- a/exp/lighthorizon/index/types/bitmap.go +++ /dev/null @@ -1,367 +0,0 @@ -package index - -import ( - "bytes" - "fmt" - "io" - "strings" - "sync" - - "github.com/stellar/go/support/ordered" - "github.com/stellar/go/xdr" -) - -const BitmapIndexVersion = 1 - -type BitmapIndex struct { - mutex sync.RWMutex - bitmap []byte - firstBit uint32 - lastBit uint32 -} - -type NamedIndices map[string]*BitmapIndex - -func NewBitmapIndex(b []byte) (*BitmapIndex, error) { - xdrBitmap := xdr.BitmapIndex{} - err := xdrBitmap.UnmarshalBinary(b) - if err != nil { - return nil, err - } - - return NewBitmapIndexFromXDR(xdrBitmap), nil -} - -func NewBitmapIndexFromXDR(index xdr.BitmapIndex) *BitmapIndex { - return &BitmapIndex{ - bitmap: index.Bitmap[:], - firstBit: uint32(index.FirstBit), - lastBit: uint32(index.LastBit), - } -} - -func (i *BitmapIndex) Size() int { - return len(i.bitmap) -} - -func (i *BitmapIndex) SetActive(index uint32) error { - i.mutex.Lock() - defer i.mutex.Unlock() - return i.setActive(index) -} - -func (i *BitmapIndex) SetInactive(index uint32) error { - i.mutex.Lock() - defer i.mutex.Unlock() - return i.setInactive(index) -} - -// bitShiftLeft returns a byte with the bit set corresponding to the index. In -// other words, it flips the bit corresponding to the index's "position" mod-8. -func bitShiftLeft(index uint32) byte { - if index%8 == 0 { - return 1 - } else { - return byte(1) << (8 - index%8) - } -} - -// rangeFirstBit returns the index of the first *possible* active bit in the -// bitmap. In other words, if you just have SetActive(12), this will return 9, -// because you have one byte (0b0001_0000) and the *first* value the bitmap can -// represent is 9. -func (i *BitmapIndex) rangeFirstBit() uint32 { - return (i.firstBit-1)/8*8 + 1 -} - -// rangeLastBit returns the index of the last *possible* active bit in the -// bitmap. In other words, if you just have SetActive(12), this will return 16, -// because you have one byte (0b0001_0000) and the *last* value the bitmap can -// represent is 16. -func (i *BitmapIndex) rangeLastBit() uint32 { - return i.rangeFirstBit() + uint32(len(i.bitmap))*8 - 1 -} - -func (i *BitmapIndex) setActive(index uint32) error { - if i.firstBit == 0 { - i.firstBit = index - i.lastBit = index - b := bitShiftLeft(index) - i.bitmap = []byte{b} - } else { - if index >= i.rangeFirstBit() && index <= i.rangeLastBit() { - // Update the bit in existing range - b := bitShiftLeft(index) - loc := (index - i.rangeFirstBit()) / 8 - i.bitmap[loc] = i.bitmap[loc] | b - - if index < i.firstBit { - i.firstBit = index - } - if index > i.lastBit { - i.lastBit = index - } - } else { - // Expand the bitmap - if index < i.rangeFirstBit() { - // ...to the left - newBytes := make([]byte, distance(index, i.rangeFirstBit())) - i.bitmap = append(newBytes, i.bitmap...) - b := bitShiftLeft(index) - i.bitmap[0] = i.bitmap[0] | b - - i.firstBit = index - } else if index > i.rangeLastBit() { - // ... to the right - newBytes := make([]byte, distance(i.rangeLastBit(), index)) - i.bitmap = append(i.bitmap, newBytes...) - b := bitShiftLeft(index) - loc := (index - i.rangeFirstBit()) / 8 - i.bitmap[loc] = i.bitmap[loc] | b - - i.lastBit = index - } - } - } - - return nil -} - -func (i *BitmapIndex) setInactive(index uint32) error { - // Is this index even active in the first place? - if i.firstBit == 0 || index < i.rangeFirstBit() || index > i.rangeLastBit() { - return nil // not really an error - } - - loc := (index - i.rangeFirstBit()) / 8 // which byte? - b := bitShiftLeft(index) // which bit w/in the byte? - i.bitmap[loc] &= ^b // unset only that bit - - // If unsetting this bit made the first byte empty OR we unset the earliest - // set bit, we need to find the next "first" active bit. - if loc == 0 && i.firstBit == index { - // find the next active bit to set as the start - nextBit, err := i.nextActiveBit(index) - if err == io.EOF { - i.firstBit = 0 - i.lastBit = 0 - i.bitmap = []byte{} - } else if err != nil { - return err - } else { - // Trim all (now-)empty bytes off the front. - i.bitmap = i.bitmap[distance(i.firstBit, nextBit):] - i.firstBit = nextBit - } - } else if int(loc) == len(i.bitmap)-1 { - idx := -1 - - if i.bitmap[loc] == 0 { - // find the latest non-empty byte, to set as the new "end" - j := len(i.bitmap) - 1 - for i.bitmap[j] == 0 { - j-- - } - - i.bitmap = i.bitmap[:j+1] - idx = 8 - } else if i.lastBit == index { - // Get the "bit number" of the last active bit (i.e. the one we just - // turned off) to mark the starting point for the search. - idx = 8 - if index%8 != 0 { - idx = int(index % 8) - } - } - - // Do we need to adjust the range? Imagine we had 0b0011_0100 and we - // unset the last active bit. - // ^ - // Then, we need to adjust our internal lastBit tracker to represent the - // ^ bit above. This means finding the first previous set bit. - if idx > -1 { - l := uint32(len(i.bitmap) - 1) - // Imagine we had 0b0011_0100 and we unset the last active bit. - // ^ - // Then, we need to adjust our internal lastBit tracker to represent - // the ^ bit above. This means finding the first previous set bit. - j, ok := int(idx), false - for ; j >= 0 && !ok; j-- { - _, ok = maxBitAfter(i.bitmap[l], uint32(j)) - } - - // We know from the earlier conditional that *some* bit is set, so - // we know that j represents the index of the bit that's the new - // "last active" bit. - firstByte := i.rangeFirstBit() - i.lastBit = firstByte + (l * 8) + uint32(j) + 1 - } - } - - return nil -} - -//lint:ignore U1000 Ignore unused function temporarily -func (i *BitmapIndex) isActive(index uint32) bool { - if index >= i.firstBit && index <= i.lastBit { - b := bitShiftLeft(index) - loc := (index - i.rangeFirstBit()) / 8 - return i.bitmap[loc]&b != 0 - } else { - return false - } -} - -func (i *BitmapIndex) iterate(f func(index uint32)) error { - i.mutex.RLock() - defer i.mutex.RUnlock() - - if i.firstBit == 0 { - return nil - } - - f(i.firstBit) - curr := i.firstBit - - for { - var err error - curr, err = i.nextActiveBit(curr + 1) - if err != nil { - if err == io.EOF { - break - } - return err - } - - f(curr) - } - - return nil -} - -func (i *BitmapIndex) Merge(other *BitmapIndex) error { - i.mutex.Lock() - defer i.mutex.Unlock() - - var err error - other.iterate(func(index uint32) { - if err != nil { - return - } - err = i.setActive(index) - }) - - return err -} - -// NextActiveBit returns the next bit position (inclusive) where this index is -// active. "Inclusive" means that if it's already active at `position`, this -// returns `position`. -func (i *BitmapIndex) NextActiveBit(position uint32) (uint32, error) { - i.mutex.RLock() - defer i.mutex.RUnlock() - return i.nextActiveBit(position) -} - -func (i *BitmapIndex) nextActiveBit(position uint32) (uint32, error) { - if i.firstBit == 0 || position > i.lastBit { - // We're past the end. - // TODO: Should this be an error? or how should we signal NONE here? - return 0, io.EOF - } - - if position < i.firstBit { - position = i.firstBit - } - - // Must be within the range, find the first non-zero after our start - loc := (position - i.rangeFirstBit()) / 8 - - // Is it in the same byte? - if shift, ok := maxBitAfter(i.bitmap[loc], (position-1)%8); ok { - return i.rangeFirstBit() + (loc * 8) + shift, nil - } - - // Scan bytes after - loc++ - for ; loc < uint32(len(i.bitmap)); loc++ { - // Find the offset of the set bit - if shift, ok := maxBitAfter(i.bitmap[loc], 0); ok { - return i.rangeFirstBit() + (loc * 8) + shift, nil - } - } - - // all bits after this were zero - // TODO: Should this be an error? or how should we signal NONE here? - return 0, io.EOF -} - -func (i *BitmapIndex) ToXDR() xdr.BitmapIndex { - i.mutex.RLock() - defer i.mutex.RUnlock() - - return xdr.BitmapIndex{ - FirstBit: xdr.Uint32(i.firstBit), - LastBit: xdr.Uint32(i.lastBit), - Bitmap: i.bitmap, - } -} - -func (i *BitmapIndex) Buffer() *bytes.Buffer { - i.mutex.RLock() - defer i.mutex.RUnlock() - - xdrBitmap := i.ToXDR() - b, err := xdrBitmap.MarshalBinary() - if err != nil { - panic(err) - } - return bytes.NewBuffer(b) -} - -// Flush flushes the index data to byte slice in index format. -func (i *BitmapIndex) Flush() []byte { - return i.Buffer().Bytes() -} - -// DebugCompare returns a string that compares this bitmap to another bitmap -// byte-by-byte in binary form as two columns. -func (i *BitmapIndex) DebugCompare(j *BitmapIndex) string { - output := make([]string, ordered.Max(len(i.bitmap), len(j.bitmap))) - for n := 0; n < len(output); n++ { - if n < len(i.bitmap) { - output[n] += fmt.Sprintf("%08b", i.bitmap[n]) - } else { - output[n] += " " - } - - output[n] += " | " - - if n < len(j.bitmap) { - output[n] += fmt.Sprintf("%08b", j.bitmap[n]) - } - } - - return strings.Join(output, "\n") -} - -func maxBitAfter(b byte, after uint32) (uint32, bool) { - if b == 0 { - // empty byte - return 0, false - } - - for shift := uint32(after); shift < 8; shift++ { - mask := byte(0b1000_0000) >> shift - if mask&b != 0 { - return shift, true - } - } - return 0, false -} - -// distance returns how many bytes occur between the two given indices. Note -// that j >= i, otherwise the result will be negative. -func distance(i, j uint32) int { - return (int(j)-1)/8 - (int(i)-1)/8 -} diff --git a/exp/lighthorizon/index/types/bitmap_test.go b/exp/lighthorizon/index/types/bitmap_test.go deleted file mode 100644 index c5e7864872..0000000000 --- a/exp/lighthorizon/index/types/bitmap_test.go +++ /dev/null @@ -1,382 +0,0 @@ -package index - -import ( - "fmt" - "io" - "math/rand" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewFromBytes(t *testing.T) { - for i := uint32(1); i < 200; i++ { - t.Run(fmt.Sprintf("New%d", i), func(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(i) - b := index.Flush() - newIndex, err := NewBitmapIndex(b) - require.NoError(t, err) - assert.Equal(t, index.firstBit, newIndex.firstBit) - assert.Equal(t, index.lastBit, newIndex.lastBit) - assert.Equal(t, index.bitmap, newIndex.bitmap) - }) - } -} - -func TestSetActive(t *testing.T) { - cases := []struct { - checkpoint uint32 - rangeFirstCheckpoint uint32 - bitmap []byte - }{ - {1, 1, []byte{0b1000_0000}}, - {2, 1, []byte{0b0100_0000}}, - {3, 1, []byte{0b0010_0000}}, - {4, 1, []byte{0b0001_0000}}, - {5, 1, []byte{0b0000_1000}}, - {6, 1, []byte{0b0000_0100}}, - {7, 1, []byte{0b0000_0010}}, - {8, 1, []byte{0b0000_0001}}, - - {9, 9, []byte{0b1000_0000}}, - {10, 9, []byte{0b0100_0000}}, - {11, 9, []byte{0b0010_0000}}, - {12, 9, []byte{0b0001_0000}}, - {13, 9, []byte{0b0000_1000}}, - {14, 9, []byte{0b0000_0100}}, - {15, 9, []byte{0b0000_0010}}, - {16, 9, []byte{0b0000_0001}}, - } - - for _, tt := range cases { - t.Run(fmt.Sprintf("init_%d", tt.checkpoint), func(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(tt.checkpoint) - - assert.Equal(t, tt.bitmap, index.bitmap) - assert.Equal(t, tt.rangeFirstCheckpoint, index.rangeFirstBit()) - assert.Equal(t, tt.checkpoint, index.firstBit) - assert.Equal(t, tt.checkpoint, index.lastBit) - }) - } - - // Update current bitmap right - index := &BitmapIndex{} - index.SetActive(1) - assert.Equal(t, uint32(1), index.firstBit) - assert.Equal(t, uint32(1), index.lastBit) - index.SetActive(8) - assert.Equal(t, []byte{0b1000_0001}, index.bitmap) - assert.Equal(t, uint32(1), index.firstBit) - assert.Equal(t, uint32(8), index.lastBit) - - // Update current bitmap left - index = &BitmapIndex{} - index.SetActive(8) - assert.Equal(t, uint32(8), index.firstBit) - assert.Equal(t, uint32(8), index.lastBit) - index.SetActive(1) - assert.Equal(t, []byte{0b1000_0001}, index.bitmap) - assert.Equal(t, uint32(1), index.firstBit) - assert.Equal(t, uint32(8), index.lastBit) - - index = &BitmapIndex{} - index.SetActive(10) - index.SetActive(9) - index.SetActive(16) - assert.Equal(t, []byte{0b1100_0001}, index.bitmap) - assert.Equal(t, uint32(9), index.firstBit) - assert.Equal(t, uint32(16), index.lastBit) - - // Expand bitmap to the left - index = &BitmapIndex{} - index.SetActive(10) - index.SetActive(1) - assert.Equal(t, []byte{0b1000_0000, 0b0100_0000}, index.bitmap) - assert.Equal(t, uint32(1), index.firstBit) - assert.Equal(t, uint32(10), index.lastBit) - - index = &BitmapIndex{} - index.SetActive(17) - index.SetActive(2) - assert.Equal(t, []byte{0b0100_0000, 0b0000_0000, 0b1000_0000}, index.bitmap) - assert.Equal(t, uint32(2), index.firstBit) - assert.Equal(t, uint32(17), index.lastBit) - - // Expand bitmap to the right - index = &BitmapIndex{} - index.SetActive(1) - index.SetActive(10) - assert.Equal(t, []byte{0b1000_0000, 0b0100_0000}, index.bitmap) - assert.Equal(t, uint32(1), index.firstBit) - assert.Equal(t, uint32(10), index.lastBit) - - index = &BitmapIndex{} - index.SetActive(2) - index.SetActive(17) - assert.Equal(t, []byte{0b0100_0000, 0b0000_0000, 0b1000_0000}, index.bitmap) - assert.Equal(t, uint32(2), index.firstBit) - assert.Equal(t, uint32(17), index.lastBit) - - index = &BitmapIndex{} - index.SetActive(17) - index.SetActive(26) - assert.Equal(t, []byte{0b1000_0000, 0b0100_0000}, index.bitmap) - assert.Equal(t, uint32(17), index.firstBit) - assert.Equal(t, uint32(26), index.lastBit) -} - -// TestSetInactive ensures that you can flip active bits off and the bitmap -// compresses in size accordingly. -func TestSetInactive(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(17) - index.SetActive(17 + 9) - index.SetActive(17 + 9 + 10) - assert.Equal(t, []byte{0b1000_0000, 0b0100_0000, 0b0001_0000}, index.bitmap) - - // disabling bits should work - index.SetInactive(17) - assert.False(t, index.isActive(17)) - - // it should trim off the first byte now - assert.Equal(t, []byte{0b0100_0000, 0b0001_0000}, index.bitmap) - assert.EqualValues(t, 17+9, index.firstBit) - assert.EqualValues(t, 17+9+10, index.lastBit) - - // it should compress empty bytes on shrink - index = &BitmapIndex{} - index.SetActive(1) - index.SetActive(1 + 2) - index.SetActive(1 + 9) - index.SetActive(1 + 9 + 8 + 9) - assert.Equal(t, []byte{0b1010_0000, 0b0100_0000, 0b0000_0000, 0b0010_0000}, index.bitmap) - - // ...from the left - index.SetInactive(1) - assert.Equal(t, []byte{0b0010_0000, 0b0100_0000, 0b0000_0000, 0b0010_0000}, index.bitmap) - index.SetInactive(3) - assert.Equal(t, []byte{0b0100_0000, 0b0000_0000, 0b0010_0000}, index.bitmap) - assert.EqualValues(t, 1+9, index.firstBit) - assert.EqualValues(t, 1+9+8+9, index.lastBit) - - // ...and the right - index.SetInactive(1 + 9 + 8 + 9) - assert.Equal(t, []byte{0b0100_0000}, index.bitmap) - assert.EqualValues(t, 1+9, index.firstBit) - assert.EqualValues(t, 1+9, index.lastBit) - - // ensure right-hand compression it works for multiple bytes, too - index = &BitmapIndex{} - index.SetActive(2) - index.SetActive(2 + 2) - index.SetActive(2 + 9) - index.SetActive(2 + 9 + 8 + 6) - index.SetActive(2 + 9 + 8 + 9) - index.SetActive(2 + 9 + 8 + 10) - assert.Equal(t, []byte{0b0101_0000, 0b0010_0000, 0b0000_0000, 0b1001_1000}, index.bitmap) - - index.setInactive(2 + 9 + 8 + 10) - assert.Equal(t, []byte{0b0101_0000, 0b0010_0000, 0b0000_0000, 0b1001_0000}, index.bitmap) - assert.EqualValues(t, 2+9+8+9, index.lastBit) - - index.setInactive(2 + 9 + 8 + 9) - assert.Equal(t, []byte{0b0101_0000, 0b0010_0000, 0b0000_0000, 0b1000_0000}, index.bitmap) - assert.EqualValues(t, 2+9+8+6, index.lastBit) - - index.setInactive(2 + 9 + 8 + 6) - assert.Equal(t, []byte{0b0101_0000, 0b0010_0000}, index.bitmap) - assert.EqualValues(t, 2, index.firstBit) - assert.EqualValues(t, 2+9, index.lastBit) - - index.setInactive(2 + 2) - assert.Equal(t, []byte{0b0100_0000, 0b0010_0000}, index.bitmap) - assert.EqualValues(t, 2, index.firstBit) - assert.EqualValues(t, 2+9, index.lastBit) - - index.setInactive(1) // should be a no-op - assert.Equal(t, []byte{0b0100_0000, 0b0010_0000}, index.bitmap) - assert.EqualValues(t, 2, index.firstBit) - assert.EqualValues(t, 2+9, index.lastBit) -} - -// TestFuzzerSetInactive attempt to fuzz random bits into two bitmap sets, one -// by addition, and one by subtraction - then, it compares the outcome. -func TestFuzzySetUnset(t *testing.T) { - permLen := uint32(128) // should be a multiple of 8 - setBitsCount := permLen / 2 - - for n := 0; n < 10_000; n++ { - randBits := rand.Perm(int(permLen)) - setBits := randBits[:setBitsCount] - clearBits := randBits[setBitsCount:] - - // set all first, then clear the others - clearBitmap := &BitmapIndex{} - for i := uint32(1); i <= permLen; i++ { - clearBitmap.setActive(i) - } - - setBitmap := &BitmapIndex{} - for i := range setBits { - setBitmap.setActive(uint32(setBits[i]) + 1) - clearBitmap.setInactive(uint32(clearBits[i]) + 1) - } - - require.Equalf(t, setBitmap, clearBitmap, - "bitmaps aren't equal:\n%s", setBitmap.DebugCompare(clearBitmap)) - } -} - -func TestNextActive(t *testing.T) { - t.Run("empty", func(t *testing.T) { - index := &BitmapIndex{} - - i, err := index.NextActiveBit(0) - assert.Equal(t, uint32(0), i) - assert.EqualError(t, err, io.EOF.Error()) - }) - - t.Run("one byte", func(t *testing.T) { - t.Run("after last", func(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(3) - - // 16 is well-past the end - i, err := index.NextActiveBit(16) - assert.Equal(t, uint32(0), i) - assert.EqualError(t, err, io.EOF.Error()) - }) - - t.Run("only one bit in the byte", func(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(1) - - i, err := index.NextActiveBit(1) - assert.NoError(t, err) - assert.Equal(t, uint32(1), i) - }) - - t.Run("only one bit in the byte (offset)", func(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(9) - - i, err := index.NextActiveBit(1) - assert.NoError(t, err) - assert.Equal(t, uint32(9), i) - }) - - severalSet := &BitmapIndex{} - severalSet.SetActive(9) - severalSet.SetActive(11) - - t.Run("several bits set (first)", func(t *testing.T) { - i, err := severalSet.NextActiveBit(9) - assert.NoError(t, err) - assert.Equal(t, uint32(9), i) - }) - - t.Run("several bits set (second)", func(t *testing.T) { - i, err := severalSet.NextActiveBit(10) - assert.NoError(t, err) - assert.Equal(t, uint32(11), i) - }) - - t.Run("several bits set (second, inclusive)", func(t *testing.T) { - i, err := severalSet.NextActiveBit(11) - assert.NoError(t, err) - assert.Equal(t, uint32(11), i) - }) - }) - - t.Run("many bytes", func(t *testing.T) { - index := &BitmapIndex{} - index.SetActive(9) - index.SetActive(129) - - // Before the first - i, err := index.NextActiveBit(8) - assert.NoError(t, err) - assert.Equal(t, uint32(9), i) - - // at the first - i, err = index.NextActiveBit(9) - assert.NoError(t, err) - assert.Equal(t, uint32(9), i) - - // In the middle - i, err = index.NextActiveBit(11) - assert.NoError(t, err) - assert.Equal(t, uint32(129), i) - - // At the end - i, err = index.NextActiveBit(129) - assert.NoError(t, err) - assert.Equal(t, uint32(129), i) - - // after the end - i, err = index.NextActiveBit(130) - assert.EqualError(t, err, io.EOF.Error()) - assert.Equal(t, uint32(0), i) - }) -} - -func TestMaxBitAfter(t *testing.T) { - for _, tc := range []struct { - b byte - after uint32 - shift uint32 - ok bool - }{ - {0b0000_0000, 0, 0, false}, - {0b0000_0000, 1, 0, false}, - {0b1000_0000, 0, 0, true}, - {0b0100_0000, 0, 1, true}, - {0b0100_0000, 1, 1, true}, - {0b0010_1000, 0, 2, true}, - {0b0010_1000, 1, 2, true}, - {0b0010_1000, 2, 2, true}, - {0b0010_1000, 3, 4, true}, - {0b0010_1000, 4, 4, true}, - {0b0000_0001, 7, 7, true}, - } { - t.Run(fmt.Sprintf("0b%b,%d", tc.b, tc.after), func(t *testing.T) { - shift, ok := maxBitAfter(tc.b, tc.after) - assert.Equal(t, tc.ok, ok) - assert.Equal(t, tc.shift, shift) - }) - } -} - -func TestMerge(t *testing.T) { - a := &BitmapIndex{} - require.NoError(t, a.SetActive(9)) - require.NoError(t, a.SetActive(129)) - - b := &BitmapIndex{} - require.NoError(t, b.SetActive(900)) - require.NoError(t, b.SetActive(1000)) - - var checkpoints []uint32 - b.iterate(func(c uint32) { - checkpoints = append(checkpoints, c) - }) - - assert.Equal(t, []uint32{900, 1000}, checkpoints) - - require.NoError(t, a.Merge(b)) - - assert.True(t, a.isActive(9)) - assert.True(t, a.isActive(129)) - assert.True(t, a.isActive(900)) - assert.True(t, a.isActive(1000)) - - checkpoints = []uint32{} - a.iterate(func(c uint32) { - checkpoints = append(checkpoints, c) - }) - - assert.Equal(t, []uint32{9, 129, 900, 1000}, checkpoints) -} diff --git a/exp/lighthorizon/index/types/trie.go b/exp/lighthorizon/index/types/trie.go deleted file mode 100644 index b5fc39c0ca..0000000000 --- a/exp/lighthorizon/index/types/trie.go +++ /dev/null @@ -1,345 +0,0 @@ -package index - -import ( - "bufio" - "encoding" - "io" - "sync" - - "github.com/stellar/go/xdr" -) - -const ( - TrieIndexVersion = 1 - - HeaderHasPrefix = 0b0000_0001 - HeaderHasValue = 0b0000_0010 - HeaderHasChildren = 0b0000_0100 -) - -type TrieIndex struct { - sync.RWMutex - Root *trieNode `json:"root"` -} - -// TODO: Store the suffix here so we can truncate the branches -type trieNode struct { - // Common prefix we ignore - Prefix []byte `json:"prefix,omitempty"` - - // The value of this node. - Value []byte `json:"value,omitempty"` - - // Any children of this node, mapped by the next byte of their path - Children map[byte]*trieNode `json:"children,omitempty"` -} - -func NewTrieIndexFromBytes(r io.Reader) (*TrieIndex, error) { - var index TrieIndex - if _, err := index.ReadFrom(r); err != nil { - return nil, err - } - return &index, nil -} - -func (index *TrieIndex) Upsert(key, value []byte) ([]byte, bool) { - if len(key) == 0 { - panic("len(key) must be > 0") - } - index.Lock() - defer index.Unlock() - return index.doUpsert(key, value) -} - -func (index *TrieIndex) doUpsert(key, value []byte) ([]byte, bool) { - if index.Root == nil { - index.Root = &trieNode{Prefix: key, Value: value} - return nil, false - } - - node := index.Root - var parent *trieNode - var parentIdx byte - splitPos := 0 - for len(key) > 0 { - for splitPos < len(node.Prefix) && len(key) > 0 { - if node.Prefix[splitPos] != key[0] { - break - } - splitPos++ - key = key[1:] - } - if splitPos != len(node.Prefix) { - // split this node - break - } - if len(key) == 0 { - // simple update-in-place at this node - break - } - - // Jump to the next child - parent = node - parentIdx = key[0] - child, ok := node.Children[key[0]] - if !ok { - if node.Children == nil { - node.Children = map[byte]*trieNode{} - } - // child doesn't exist. Insert a new node - node.Children[key[0]] = &trieNode{ - Prefix: key[1:], - Value: value, - } - return nil, false - } - node = child - key = key[1:] - splitPos = 0 - } - - // Key fully consumed just as we reached "node" - if len(key) == 0 { - if splitPos == len(node.Prefix) { - // node prefix matches (or is none), simple update-in-place - prev := node.Value - node.Value = value - return prev, true - } else { - // node has a prefix, so we need to insert a new one here and push it down - splitNode := &trieNode{ - Prefix: node.Prefix[:splitPos], // the matching segment - Value: value, - Children: map[byte]*trieNode{}, - } - splitNode.Children[node.Prefix[splitPos]] = node - node.Prefix = node.Prefix[splitPos+1:] // existing part that didn't match - if parent == nil { - index.Root = splitNode - } else { - parent.Children[parentIdx] = splitNode - } - return nil, false - } - } else { - // leftover key - if splitPos == len(node.Prefix) { - // new child - node.Children[key[0]] = &trieNode{ - Prefix: key[1:], - Value: value, - } - return nil, false - } else { - // Need to split the node - splitNode := &trieNode{ - Prefix: node.Prefix[:splitPos], - Children: map[byte]*trieNode{}, - } - splitNode.Children[node.Prefix[splitPos]] = node - splitNode.Children[key[0]] = &trieNode{Prefix: key[1:], Value: value} - node.Prefix = node.Prefix[splitPos+1:] - if parent == nil { - index.Root = splitNode - } else { - parent.Children[parentIdx] = splitNode - } - return nil, false - } - } -} - -func (index *TrieIndex) Get(key []byte) ([]byte, bool) { - index.RLock() - defer index.RUnlock() - if index.Root == nil { - return nil, false - } - - node := index.Root - splitPos := 0 - for len(key) > 0 { - for splitPos < len(node.Prefix) && len(key) > 0 { - if node.Prefix[splitPos] != key[0] { - break - } - splitPos++ - key = key[1:] - } - if splitPos != len(node.Prefix) { - // split this node - break - } - if len(key) == 0 { - // found it - return node.Value, true - } - - // Jump to the next child - child, ok := node.Children[key[0]] - if !ok { - // child doesn't exist - return nil, false - } - node = child - key = key[1:] - splitPos = 0 - } - - if len(key) == 0 { - return node.Value, true - } - return nil, false -} - -func (index *TrieIndex) Iterate(f func(key, value []byte)) { - index.RLock() - defer index.RUnlock() - if index.Root != nil { - index.Root.iterate(nil, f) - } -} - -func (node *trieNode) iterate(prefix []byte, f func(key, value []byte)) { - key := append(prefix, node.Prefix...) - if len(node.Value) > 0 { - f(key, node.Value) - } - - if node.Children != nil { - for b, child := range node.Children { - child.iterate(append(key, b), f) - } - } -} - -// TODO: For now this ignores duplicates. should it error? -func (i *TrieIndex) Merge(other *TrieIndex) error { - i.Lock() - defer i.Unlock() - - other.Iterate(func(key, value []byte) { - i.doUpsert(key, value) - }) - - return nil -} - -func (i *TrieIndex) MarshalBinary() ([]byte, error) { - i.RLock() - defer i.RUnlock() - - xdrRoot := xdr.TrieNode{} - - // Apparently this is possible? - if i.Root != nil { - xdrRoot.Prefix = i.Root.Prefix - xdrRoot.Value = i.Root.Value - xdrRoot.Children = make([]xdr.TrieNodeChild, 0, len(i.Root.Children)) - - for key, node := range i.Root.Children { - buildXdrTrie(key, node, &xdrRoot) - } - } - - xdrIndex := xdr.TrieIndex{Version: TrieIndexVersion, Root: xdrRoot} - return xdrIndex.MarshalBinary() -} - -func (i *TrieIndex) WriteTo(w io.Writer) (int64, error) { - i.RLock() - defer i.RUnlock() - - bytes, err := i.MarshalBinary() - if err != nil { - return int64(len(bytes)), err - } - - count, err := w.Write(bytes) - return int64(count), err -} - -func (i *TrieIndex) UnmarshalBinary(bytes []byte) error { - i.RLock() - defer i.RUnlock() - - xdrIndex := xdr.TrieIndex{} - err := xdrIndex.UnmarshalBinary(bytes) - if err != nil { - return err - } - - i.Root = &trieNode{ - Prefix: xdrIndex.Root.Prefix, - Value: xdrIndex.Root.Value, - Children: make(map[byte]*trieNode, len(xdrIndex.Root.Children)), - } - - for _, node := range xdrIndex.Root.Children { - buildTrie(&node, i.Root) - } - - return nil -} - -func (i *TrieIndex) ReadFrom(r io.Reader) (int64, error) { - i.RLock() - defer i.RUnlock() - - br := bufio.NewReader(r) - bytes, err := io.ReadAll(br) - if err != nil { - return int64(len(bytes)), err - } - - return int64(len(bytes)), i.UnmarshalBinary(bytes) -} - -// buildTrie recursively builds the equivalent `TrieNode` structure from raw -// XDR, creating the key->value child mapping from the flat list of children. -// Here, `xdrNode` is the node we're processing and `parent` is its non-XDR -// parent (i.e. the parent was already converted from XDR). -// -// This is the opposite of buildXdrTrie. -func buildTrie(xdrNode *xdr.TrieNodeChild, parent *trieNode) { - node := &trieNode{ - Prefix: xdrNode.Node.Prefix, - Value: xdrNode.Node.Value, - Children: make(map[byte]*trieNode, len(xdrNode.Node.Children)), - } - parent.Children[xdrNode.Key[0]] = node - - for _, child := range xdrNode.Node.Children { - buildTrie(&child, node) - } -} - -// buildXdrTrie recursively builds the XDR-equivalent TrieNode structure, where -// `i` is the node we're converting and `parent` is the already-converted -// parent. That is, the non-XDR version of `parent` should have had (`key`, `i`) -// as a child. -// -// This is the opposite of buildTrie. -func buildXdrTrie(key byte, node *trieNode, parent *xdr.TrieNode) { - self := xdr.TrieNode{ - Prefix: node.Prefix, - Value: node.Value, - Children: make([]xdr.TrieNodeChild, 0, len(node.Children)), - } - - for key, node := range node.Children { - buildXdrTrie(key, node, &self) - } - - parent.Children = append(parent.Children, xdr.TrieNodeChild{ - Key: [1]byte{key}, - Node: self, - }) -} - -// Ensure we're compatible with stdlib interfaces. -var _ io.WriterTo = &TrieIndex{} -var _ io.ReaderFrom = &TrieIndex{} - -var _ encoding.BinaryMarshaler = &TrieIndex{} -var _ encoding.BinaryUnmarshaler = &TrieIndex{} diff --git a/exp/lighthorizon/index/types/trie_test.go b/exp/lighthorizon/index/types/trie_test.go deleted file mode 100644 index 8745296429..0000000000 --- a/exp/lighthorizon/index/types/trie_test.go +++ /dev/null @@ -1,297 +0,0 @@ -package index - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "encoding/json" - "math/rand" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func randomTrie(t *testing.T, index *TrieIndex) (*TrieIndex, map[string]uint32) { - if index == nil { - index = &TrieIndex{} - } - inserts := map[string]uint32{} - numInserts := rand.Intn(100) - for j := 0; j < numInserts; j++ { - ledger := uint32(rand.Int63()) - hashBytes := make([]byte, 32) - if _, err := rand.Read(hashBytes); err != nil { - assert.NoError(t, err) - } - hash := hex.EncodeToString(hashBytes) - - inserts[hash] = ledger - b := make([]byte, 4) - binary.BigEndian.PutUint32(b, ledger) - index.Upsert([]byte(hash), b) - } - return index, inserts -} - -func TestTrieIndex(t *testing.T) { - for i := 0; i < 10_000; i++ { - index, inserts := randomTrie(t, nil) - - for key, expected := range inserts { - value, ok := index.Get([]byte(key)) - require.Truef(t, ok, "Key not found: %s", key) - ledger := binary.BigEndian.Uint32(value) - assert.Equalf(t, expected, ledger, - "Key %s found: %v, expected: %v", key, ledger, expected) - } - } -} - -func TestTrieIndexUpsertBasic(t *testing.T) { - index := &TrieIndex{} - - key := "key" - prev, ok := index.Upsert([]byte(key), []byte("a")) - assert.Nil(t, prev) - assert.Falsef(t, ok, "expected nil, got prev: %q", string(prev)) - - prev, ok = index.Upsert([]byte(key), []byte("b")) - assert.Equal(t, "a", string(prev)) - assert.Truef(t, ok, "expected 'a', got prev: %q", string(prev)) - - prev, ok = index.Upsert([]byte(key), []byte("c")) - assert.Equal(t, "b", string(prev)) - assert.Truef(t, ok, "expected 'b', got prev: %q", string(prev)) -} - -func TestTrieIndexSuffixes(t *testing.T) { - index := &TrieIndex{} - - prev, ok := index.Upsert([]byte("a"), []byte("a")) - require.False(t, ok) - require.Nil(t, prev) - - prev, ok = index.Upsert([]byte("ab"), []byte("ab")) - require.False(t, ok) - require.Nil(t, prev) - - prev, ok = index.Get([]byte("a")) - require.True(t, ok) - require.Equal(t, "a", string(prev)) - - prev, ok = index.Get([]byte("ab")) - require.True(t, ok) - require.Equal(t, "ab", string(prev)) - - prev, ok = index.Upsert([]byte("a"), []byte("b")) - require.True(t, ok) - require.Equal(t, "a", string(prev)) - - prev, ok = index.Get([]byte("a")) - require.True(t, ok) - require.Equal(t, "b", string(prev)) -} - -func TestTrieIndexSerialization(t *testing.T) { - for i := 0; i < 10_000; i++ { - t.Run(strconv.FormatInt(int64(i), 10), func(t *testing.T) { - index, inserts := randomTrie(t, nil) - - // Round-trip it to serialization and back - buf := &bytes.Buffer{} - nWritten, err := index.WriteTo(buf) - assert.NoError(t, err) - - read := &TrieIndex{} - nRead, err := read.ReadFrom(buf) - assert.NoError(t, err) - - assert.Equal(t, nWritten, nRead, "read more or less than we wrote") - - for key, expected := range inserts { - value, ok := read.Get([]byte(key)) - require.Truef(t, ok, "Key not found: %s", key) - - ledger := binary.BigEndian.Uint32(value) - assert.Equal(t, expected, ledger, "for key %s", key) - } - }) - } -} - -func requireEqualNodes(t *testing.T, expectedNode, gotNode *trieNode) { - expectedJSON, err := json.Marshal(expectedNode) - require.NoError(t, err) - expected := map[string]interface{}{} - require.NoError(t, json.Unmarshal(expectedJSON, &expected)) - - gotJSON, err := json.Marshal(gotNode) - require.NoError(t, err) - got := map[string]interface{}{} - require.NoError(t, json.Unmarshal(gotJSON, &got)) - - require.Equal(t, expected, got) -} - -func TestTrieIndexUpsertAdvanced(t *testing.T) { - // TODO: This is janky that we inspect the structure, but I want to make sure - // I've gotten the algorithms correct. - makeBase := func() *TrieIndex { - index := &TrieIndex{} - index.Upsert([]byte("annibale"), []byte{1}) - index.Upsert([]byte("annibalesco"), []byte{2}) - return index - } - - t.Run("base", func(t *testing.T) { - base := makeBase() - - baseExpected := &trieNode{ - Prefix: []byte("annibale"), - Value: []byte{1}, - Children: map[byte]*trieNode{ - byte('s'): { - Prefix: []byte("co"), - Value: []byte{2}, - }, - }, - } - requireEqualNodes(t, baseExpected, base.Root) - }) - - for _, tc := range []struct { - key string - expected *trieNode - }{ - {"annientare", &trieNode{ - Prefix: []byte("anni"), - Children: map[byte]*trieNode{ - 'b': { - Prefix: []byte("ale"), - Value: []byte{1}, - Children: map[byte]*trieNode{ - 's': { - Prefix: []byte("co"), - Value: []byte{2}, - }, - }, - }, - 'e': { - Prefix: []byte("ntare"), - Value: []byte{3}, - }, - }, - }}, - {"annibali", &trieNode{ - Prefix: []byte("annibal"), - Children: map[byte]*trieNode{ - 'e': { - Value: []byte{1}, - Children: map[byte]*trieNode{ - 's': { - Prefix: []byte("co"), - Value: []byte{2}, - }, - }, - }, - 'i': { - Value: []byte{3}, - }, - }, - }}, - {"ago", &trieNode{ - Prefix: []byte("a"), - Children: map[byte]*trieNode{ - 'n': { - Prefix: []byte("nibale"), - Value: []byte{1}, - Children: map[byte]*trieNode{ - 's': { - Prefix: []byte("co"), - Value: []byte{2}, - }, - }, - }, - 'g': { - Prefix: []byte("o"), - Value: []byte{3}, - }, - }, - }}, - {"ciao", &trieNode{ - Children: map[byte]*trieNode{ - 'a': { - Prefix: []byte("nnibale"), - Value: []byte{1}, - Children: map[byte]*trieNode{ - 's': { - Prefix: []byte("co"), - Value: []byte{2}, - }, - }, - }, - 'c': { - Prefix: []byte("iao"), - Value: []byte{3}, - }, - }, - }}, - {"anni", &trieNode{ - Prefix: []byte("anni"), - Value: []byte{3}, - Children: map[byte]*trieNode{ - 'b': { - Prefix: []byte("ale"), - Value: []byte{1}, - Children: map[byte]*trieNode{ - 's': { - Prefix: []byte("co"), - Value: []byte{2}, - }, - }, - }, - }, - }}, - } { - t.Run(tc.key, func(t *testing.T) { - // Do our upsert - index := makeBase() - index.Upsert([]byte(tc.key), []byte{3}) - - // Check the tree is shaped right - requireEqualNodes(t, tc.expected, index.Root) - - // Check the value matches expected - value, ok := index.Get([]byte(tc.key)) - require.True(t, ok) - require.Equal(t, []byte{3}, value) - }) - } -} - -func TestTrieIndexMerge(t *testing.T) { - for i := 0; i < 10_000; i++ { - a, aInserts := randomTrie(t, nil) - b, bInserts := randomTrie(t, nil) - - require.NoError(t, a.Merge(b)) - - // Should still have all the A keys - for key, expected := range aInserts { - value, ok := a.Get([]byte(key)) - require.Truef(t, ok, "Key not found: %s", key) - ledger := binary.BigEndian.Uint32(value) - assert.Equalf(t, expected, ledger, "Key %s found", key) - } - - // Should now also have all the B keys - for key, expected := range bInserts { - value, ok := a.Get([]byte(key)) - require.Truef(t, ok, "Key not found: %s", key) - ledger := binary.BigEndian.Uint32(value) - assert.Equalf(t, expected, ledger, "Key %s found", key) - } - } -} diff --git a/exp/lighthorizon/ingester/ingester.go b/exp/lighthorizon/ingester/ingester.go deleted file mode 100644 index 21bb400b50..0000000000 --- a/exp/lighthorizon/ingester/ingester.go +++ /dev/null @@ -1,55 +0,0 @@ -package ingester - -import ( - "context" - - "github.com/stellar/go/ingest" - "github.com/stellar/go/metaarchive" - - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/xdr" -) - -type IngesterConfig struct { - SourceUrl string - NetworkPassphrase string - - CacheDir string - CacheSize int - - ParallelDownloads uint -} - -type liteIngester struct { - metaarchive.MetaArchive - networkPassphrase string -} - -func (i *liteIngester) PrepareRange(ctx context.Context, r historyarchive.Range) error { - return nil -} - -func (i *liteIngester) NewLedgerTransactionReader( - ledgerCloseMeta xdr.SerializedLedgerCloseMeta, -) (LedgerTransactionReader, error) { - reader, err := ingest.NewLedgerTransactionReaderFromLedgerCloseMeta( - i.networkPassphrase, - ledgerCloseMeta.MustV0()) - - return &liteLedgerTransactionReader{reader}, err -} - -type liteLedgerTransactionReader struct { - *ingest.LedgerTransactionReader -} - -func (reader *liteLedgerTransactionReader) Read() (LedgerTransaction, error) { - ingestedTx, err := reader.LedgerTransactionReader.Read() - if err != nil { - return LedgerTransaction{}, err - } - return LedgerTransaction{LedgerTransaction: &ingestedTx}, nil -} - -var _ Ingester = (*liteIngester)(nil) // ensure conformity to the interface -var _ LedgerTransactionReader = (*liteLedgerTransactionReader)(nil) diff --git a/exp/lighthorizon/ingester/main.go b/exp/lighthorizon/ingester/main.go deleted file mode 100644 index a93636c67a..0000000000 --- a/exp/lighthorizon/ingester/main.go +++ /dev/null @@ -1,87 +0,0 @@ -package ingester - -import ( - "context" - "fmt" - "net/url" - - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/ingest" - "github.com/stellar/go/metaarchive" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" - "github.com/stellar/go/support/storage" - "github.com/stellar/go/xdr" -) - -// -// LightHorizon data model -// - -// Ingester combines a source of unpacked ledger metadata and a way to create a -// ingestion reader interface on top of it. -type Ingester interface { - metaarchive.MetaArchive - - PrepareRange(ctx context.Context, r historyarchive.Range) error - NewLedgerTransactionReader( - ledgerCloseMeta xdr.SerializedLedgerCloseMeta, - ) (LedgerTransactionReader, error) -} - -// For now, this mirrors the `ingest` library exactly, but it's replicated so -// that we can diverge in the future if necessary. -type LedgerTransaction struct { - *ingest.LedgerTransaction -} - -type LedgerTransactionReader interface { - Read() (LedgerTransaction, error) -} - -func NewIngester(config IngesterConfig) (Ingester, error) { - if config.CacheSize <= 0 { - return nil, fmt.Errorf("invalid cache size: %d", config.CacheSize) - } - - // Now, set up a simple filesystem-like access to the backend and wrap it in - // a local on-disk LRU cache if we can. - source, err := historyarchive.ConnectBackend( - config.SourceUrl, - storage.ConnectOptions{Context: context.Background()}, - ) - if err != nil { - return nil, errors.Wrapf(err, "failed to connect to %s", config.SourceUrl) - } - - parsed, err := url.Parse(config.SourceUrl) - if err != nil { - return nil, errors.Wrapf(err, "%s is not a valid URL", config.SourceUrl) - } - - if parsed.Scheme != "file" { // otherwise, already on-disk - cache, errr := storage.MakeOnDiskCache(source, config.CacheDir, uint(config.CacheSize)) - - if errr != nil { // non-fatal: warn but continue w/o cache - log.WithField("path", config.CacheDir).WithError(errr). - Warnf("Failed to create cached ledger backend") - } else { - log.WithField("path", config.CacheDir). - Infof("On-disk cache configured") - source = cache - } - } - - if config.ParallelDownloads > 1 { - log.Infof("Enabling parallel ledger fetches with %d workers", config.ParallelDownloads) - return NewParallelIngester( - metaarchive.NewMetaArchive(source), - config.NetworkPassphrase, - config.ParallelDownloads), nil - } - - return &liteIngester{ - MetaArchive: metaarchive.NewMetaArchive(source), - networkPassphrase: config.NetworkPassphrase, - }, nil -} diff --git a/exp/lighthorizon/ingester/mock_ingester.go b/exp/lighthorizon/ingester/mock_ingester.go deleted file mode 100644 index 62c377ce78..0000000000 --- a/exp/lighthorizon/ingester/mock_ingester.go +++ /dev/null @@ -1,44 +0,0 @@ -package ingester - -import ( - "context" - - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/xdr" - "github.com/stretchr/testify/mock" -) - -type MockIngester struct { - mock.Mock -} - -func (m *MockIngester) NewLedgerTransactionReader( - ledgerCloseMeta xdr.SerializedLedgerCloseMeta, -) (LedgerTransactionReader, error) { - args := m.Called(ledgerCloseMeta) - return args.Get(0).(LedgerTransactionReader), args.Error(1) -} - -func (m *MockIngester) GetLatestLedgerSequence(ctx context.Context) (uint32, error) { - args := m.Called(ctx) - return args.Get(0).(uint32), args.Error(1) -} - -func (m *MockIngester) GetLedger(ctx context.Context, sequence uint32) (xdr.SerializedLedgerCloseMeta, error) { - args := m.Called(ctx, sequence) - return args.Get(0).(xdr.SerializedLedgerCloseMeta), args.Error(1) -} - -func (m *MockIngester) PrepareRange(ctx context.Context, r historyarchive.Range) error { - args := m.Called(ctx, r) - return args.Error(0) -} - -type MockLedgerTransactionReader struct { - mock.Mock -} - -func (m *MockLedgerTransactionReader) Read() (LedgerTransaction, error) { - args := m.Called() - return args.Get(0).(LedgerTransaction), args.Error(1) -} diff --git a/exp/lighthorizon/ingester/parallel_ingester.go b/exp/lighthorizon/ingester/parallel_ingester.go deleted file mode 100644 index 133b0a37c4..0000000000 --- a/exp/lighthorizon/ingester/parallel_ingester.go +++ /dev/null @@ -1,141 +0,0 @@ -package ingester - -import ( - "context" - "sync" - "time" - - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/metaarchive" - "github.com/stellar/go/support/collections/set" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -type parallelIngester struct { - liteIngester - - ledgerFeed sync.Map // thread-safe version of map[uint32]downloadState - ledgerQueue set.ISet[uint32] - - workQueue chan uint32 - signalChan chan error -} - -type downloadState struct { - ledger xdr.SerializedLedgerCloseMeta - err error -} - -// NewParallelIngester creates an ingester on the given `ledgerSource` using the -// given `networkPassphrase` that can download ledgers in parallel via -// `workerCount` workers via `PrepareRange()`. -func NewParallelIngester( - archive metaarchive.MetaArchive, - networkPassphrase string, - workerCount uint, -) *parallelIngester { - self := ¶llelIngester{ - liteIngester: liteIngester{ - MetaArchive: archive, - networkPassphrase: networkPassphrase, - }, - ledgerFeed: sync.Map{}, - ledgerQueue: set.NewSafeSet[uint32](64), - workQueue: make(chan uint32, workerCount), - signalChan: make(chan error), - } - - // These are the workers that download & store ledgers in memory. - for j := uint(0); j < workerCount; j++ { - go func(jj uint) { - for ledgerSeq := range self.workQueue { - start := time.Now() - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - txmeta, err := self.liteIngester.GetLedger(ctx, ledgerSeq) - cancel() - - log.WithField("duration", time.Since(start)). - WithField("worker", jj).WithError(err). - Debugf("Downloaded ledger %d", ledgerSeq) - - self.ledgerFeed.Store(ledgerSeq, downloadState{txmeta, err}) - self.signalChan <- err - } - }(j) - } - - return self -} - -// PrepareRange will create a set of parallel worker routines that feed ledgers -// to a channel in the order they're downloaded and store the results in an -// array. You can use this to download ledgers in parallel to fetching them -// individually via `GetLedger()`. `PrepareRange()` is thread-safe. -// -// Note: The passed in range `r` is inclusive of the boundaries. -func (i *parallelIngester) PrepareRange(ctx context.Context, r historyarchive.Range) error { - // The taskmaster adds ledger sequence numbers to the work queue. - go func() { - start := time.Now() - defer func() { - log.WithField("duration", time.Since(start)). - WithError(ctx.Err()). - Infof("Download of ledger range: [%d, %d] (%d ledgers) complete", - r.Low, r.High, r.Size()) - }() - - for seq := r.Low; seq <= r.High; seq++ { - if ctx.Err() != nil { - log.Warnf("Cancelling remaining downloads ([%d, %d]): %v", - seq, r.High, ctx.Err()) - break - } - - // Adding this to the "set of ledgers being downloaded in parallel" - // means that if a GetLedger() request happens in this range but - // outside of the realm of processing, it can be prioritized by the - // normal, direct download. - i.ledgerQueue.Add(seq) - - i.workQueue <- seq // blocks until there's an available worker - - // We don't remove from the queue here, preferring to remove when - // it's actually pulled from the worker. Removing here would mean - // you could have multiple instances of a ledger download happening. - } - }() - - return nil -} - -func (i *parallelIngester) GetLedger( - ctx context.Context, ledgerSeq uint32, -) (xdr.SerializedLedgerCloseMeta, error) { - // If the requested ledger is out of the queued up ranges, we can fall back - // to the default non-parallel download method. - if !i.ledgerQueue.Contains(ledgerSeq) { - return i.liteIngester.GetLedger(ctx, ledgerSeq) - } - - // If the ledger isn't available yet, wait for the download worker. - var err error - for err == nil { - if iState, ok := i.ledgerFeed.Load(ledgerSeq); ok { - state := iState.(downloadState) - i.ledgerFeed.Delete(ledgerSeq) - i.ledgerQueue.Remove(ledgerSeq) - return state.ledger, state.err - } - - select { - case err = <-i.signalChan: // blocks until another ledger downloads - case <-ctx.Done(): - err = ctx.Err() - } - } - - return xdr.SerializedLedgerCloseMeta{}, err -} - -var _ Ingester = (*parallelIngester)(nil) // ensure conformity to the interface diff --git a/exp/lighthorizon/ingester/participants.go b/exp/lighthorizon/ingester/participants.go deleted file mode 100644 index ebc49173cf..0000000000 --- a/exp/lighthorizon/ingester/participants.go +++ /dev/null @@ -1,35 +0,0 @@ -package ingester - -import ( - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/support/collections/set" - "github.com/stellar/go/xdr" -) - -// GetTransactionParticipants takes a LedgerTransaction and returns a set of all -// participants (accounts) in the transaction. If there is any error, it will -// return nil and the error. -func GetTransactionParticipants(tx LedgerTransaction) (set.Set[string], error) { - participants, err := index.GetTransactionParticipants(*tx.LedgerTransaction) - if err != nil { - return nil, err - } - set := set.NewSet[string](len(participants)) - set.AddSlice(participants) - return set, nil -} - -// GetOperationParticipants takes a LedgerTransaction, the Operation within the -// transaction, and the 0-based index of the operation within the transaction. -// It will return a set of all participants (accounts) in the operation. If -// there is any error, it will return nil and the error. -func GetOperationParticipants(tx LedgerTransaction, op xdr.Operation, opIndex int) (set.Set[string], error) { - participants, err := index.GetOperationParticipants(*tx.LedgerTransaction, op, opIndex) - if err != nil { - return nil, err - } - - set := set.NewSet[string](len(participants)) - set.AddSlice(participants) - return set, nil -} diff --git a/exp/lighthorizon/main.go b/exp/lighthorizon/main.go deleted file mode 100644 index f7c502d465..0000000000 --- a/exp/lighthorizon/main.go +++ /dev/null @@ -1,183 +0,0 @@ -package main - -import ( - "context" - "net/http" - - "github.com/go-chi/chi" - "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - - "github.com/stellar/go/exp/lighthorizon/actions" - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/exp/lighthorizon/services" - "github.com/stellar/go/exp/lighthorizon/tools" - - "github.com/stellar/go/network" - "github.com/stellar/go/support/log" -) - -const ( - HorizonLiteVersion = "0.0.1-alpha" - defaultCacheSize = (60 * 60 * 24) / 6 // 1 day of ledgers @ 6s each -) - -func main() { - log.SetLevel(logrus.InfoLevel) // default for subcommands - - cmd := &cobra.Command{ - Use: "lighthorizon ", - Long: "Horizon Lite command suite", - RunE: func(cmd *cobra.Command, args []string) error { - return cmd.Usage() // require a subcommand - }, - } - - serve := &cobra.Command{ - Use: "serve ", - Long: `Starts the Horizon Lite server, binding it to port 8080 on all -local interfaces of the host. You can refer to the OpenAPI documentation located -at the /api endpoint to see what endpoints are supported. - -The should be a URL to meta archives from which to read unpacked -ledger files, while the should be a URL containing indices that -break down accounts by active ledgers.`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 2 { - cmd.Usage() - return - } - - sourceUrl, indexStoreUrl := args[0], args[1] - - networkPassphrase, _ := cmd.Flags().GetString("network-passphrase") - switch networkPassphrase { - case "testnet": - networkPassphrase = network.TestNetworkPassphrase - case "pubnet": - networkPassphrase = network.PublicNetworkPassphrase - } - - cacheDir, _ := cmd.Flags().GetString("ledger-cache") - cacheSize, _ := cmd.Flags().GetUint("ledger-cache-size") - logLevelParam, _ := cmd.Flags().GetString("log-level") - downloadCount, _ := cmd.Flags().GetUint("parallel-downloads") - - L := log.WithField("service", "horizon-lite") - logLevel, err := logrus.ParseLevel(logLevelParam) - if err != nil { - log.Warnf("Failed to parse log level '%s', defaulting to 'info'.", logLevelParam) - logLevel = log.InfoLevel - } - L.SetLevel(logLevel) - L.Info("Starting lighthorizon!") - - registry := prometheus.NewRegistry() - indexStore, err := index.ConnectWithConfig(index.StoreConfig{ - URL: indexStoreUrl, - Log: L.WithField("service", "index"), - Metrics: registry, - }) - if err != nil { - log.Fatal(err) - return - } - - ingester, err := ingester.NewIngester(ingester.IngesterConfig{ - SourceUrl: sourceUrl, - NetworkPassphrase: networkPassphrase, - CacheDir: cacheDir, - CacheSize: int(cacheSize), - ParallelDownloads: downloadCount, - }) - if err != nil { - log.Fatal(err) - return - } - - latestLedger, err := ingester.GetLatestLedgerSequence(context.Background()) - if err != nil { - log.Fatalf("Failed to retrieve latest ledger from %s: %v", sourceUrl, err) - return - } - log.Infof("The latest ledger stored at %s is %d.", sourceUrl, latestLedger) - - cachePreloadCount, _ := cmd.Flags().GetUint32("ledger-cache-preload") - cachePreloadStart, _ := cmd.Flags().GetUint32("ledger-cache-preload-start") - if cachePreloadCount > 0 { - if cacheDir == "" { - log.Fatalf("--ledger-cache-preload=%d specified but no "+ - "--ledger-cache directory provided.", - cachePreloadCount) - return - } else { - startLedger := int(latestLedger) - int(cachePreloadCount) - if cachePreloadStart > 0 { - startLedger = int(cachePreloadStart) - } - if startLedger <= 0 { - log.Warnf("Starting ledger invalid (%d), defaulting to 2.", - startLedger) - startLedger = 2 - } - - log.Infof("Preloading cache at %s with %d ledgers, starting at ledger %d.", - cacheDir, startLedger, cachePreloadCount) - go func() { - tools.BuildCache(sourceUrl, cacheDir, - uint32(startLedger), cachePreloadCount, false) - }() - } - } - - Config := services.Config{ - Ingester: ingester, - Passphrase: networkPassphrase, - IndexStore: indexStore, - Metrics: services.NewMetrics(registry), - } - - lightHorizon := services.LightHorizon{ - Transactions: &services.TransactionRepository{ - Config: Config, - }, - Operations: &services.OperationRepository{ - Config: Config, - }, - } - - // Inject our config into the root response. - router := lightHorizonHTTPHandler(registry, lightHorizon).(*chi.Mux) - router.MethodFunc(http.MethodGet, "/", actions.Root(actions.RootResponse{ - Version: HorizonLiteVersion, - LedgerSource: sourceUrl, - IndexSource: indexStoreUrl, - - LatestLedger: latestLedger, - })) - - log.Fatal(http.ListenAndServe(":8080", router)) - }, - } - - serve.Flags().String("log-level", "info", - "logging level: 'info', 'debug', 'warn', 'error', 'panic', 'fatal', or 'trace'") - serve.Flags().String("network-passphrase", "pubnet", "network passphrase") - serve.Flags().String("ledger-cache", "", "path to cache frequently-used ledgers; "+ - "if left empty, uses a temporary directory") - serve.Flags().Uint("ledger-cache-size", defaultCacheSize, - "number of ledgers to store in the cache") - serve.Flags().Uint32("ledger-cache-preload", 0, - "should the cache come preloaded with the latest ledgers?") - serve.Flags().Uint32("ledger-cache-preload-start", 0, - "the preload should start at ledger ") - serve.Flags().Uint("parallel-downloads", 1, - "how many workers should download ledgers in parallel?") - - cmd.AddCommand(serve) - tools.AddCacheCommands(cmd) - tools.AddIndexCommands(cmd) - cmd.Execute() -} diff --git a/exp/lighthorizon/services/cursor.go b/exp/lighthorizon/services/cursor.go deleted file mode 100644 index 8f2d2b0b5c..0000000000 --- a/exp/lighthorizon/services/cursor.go +++ /dev/null @@ -1,102 +0,0 @@ -package services - -import ( - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/toid" -) - -// CursorManager describes a way to control how a cursor advances for a -// particular indexing strategy. -type CursorManager interface { - Begin(cursor int64) (int64, error) - Advance(times uint) (int64, error) -} - -type AccountActivityCursorManager struct { - AccountId string - - store index.Store - lastCursor *toid.ID -} - -func NewCursorManagerForAccountActivity(store index.Store, accountId string) *AccountActivityCursorManager { - return &AccountActivityCursorManager{AccountId: accountId, store: store} -} - -func (c *AccountActivityCursorManager) Begin(cursor int64) (int64, error) { - freq := checkpointManager.GetCheckpointFrequency() - id := toid.Parse(cursor) - lastCheckpoint := uint32(0) - if id.LedgerSequence >= int32(checkpointManager.GetCheckpointFrequency()) { - lastCheckpoint = index.GetCheckpointNumber(uint32(id.LedgerSequence)) - } - - // We shouldn't take the provided cursor for granted: instead, we should - // skip ahead to the first active ledger that's >= the given cursor. - // - // For example, someone might say ?cursor=0 but the first active checkpoint - // is actually 40M ledgers in. - firstCheckpoint, err := c.store.NextActive(c.AccountId, allTransactionsIndex, lastCheckpoint) - if err != nil { - return cursor, err - } - - nextLedger := (firstCheckpoint - 1) * freq - - // However, if the given cursor is actually *more* specific than the index - // can give us (e.g. somewhere *within* an active checkpoint range), prefer - // it rather than starting over. - if nextLedger < uint32(id.LedgerSequence) { - better := toid.Parse(cursor) - c.lastCursor = &better - return cursor, nil - } - - c.lastCursor = toid.New(int32(nextLedger), 1, 1) - return c.lastCursor.ToInt64(), nil -} - -func (c *AccountActivityCursorManager) Advance(times uint) (int64, error) { - if c.lastCursor == nil { - panic("invalid cursor, call Begin() first") - } - - // - // Advancing the cursor means deciding whether or not we need to query - // the index. - // - freq := checkpointManager.GetCheckpointFrequency() - - for i := uint(1); i <= times; i++ { - lastLedger := uint32(c.lastCursor.LedgerSequence) - - if checkpointManager.IsCheckpoint(lastLedger) { - // If the last cursor we looked at was a checkpoint ledger, then we - // need to jump ahead to the next checkpoint. Note that NextActive() - // is "inclusive" so if the parameter is an active checkpoint it - // will return itself. - checkpoint := index.GetCheckpointNumber(uint32(c.lastCursor.LedgerSequence)) - checkpoint, err := c.store.NextActive(c.AccountId, allTransactionsIndex, checkpoint+1) - if err != nil { - return c.lastCursor.ToInt64(), err - } - - // We add a -1 here because an active checkpoint indicates that an - // account had activity in the *previous* 64 ledgers, so we need to - // backtrack to that ledger range. - c.lastCursor = toid.New(int32((checkpoint-1)*freq), 1, 1) - } else { - // Otherwise, we can just bump the ledger number. - c.lastCursor = toid.New(int32(lastLedger+1), 1, 1) - } - } - - return c.lastCursor.ToInt64(), nil -} - -var _ CursorManager = (*AccountActivityCursorManager)(nil) // ensure conformity to the interface - -// getLedgerFromCursor is a helpful way to turn a cursor into a ledger number -func getLedgerFromCursor(cursor int64) uint32 { - return uint32(toid.Parse(cursor).LedgerSequence) -} diff --git a/exp/lighthorizon/services/cursor_test.go b/exp/lighthorizon/services/cursor_test.go deleted file mode 100644 index 2112ae3715..0000000000 --- a/exp/lighthorizon/services/cursor_test.go +++ /dev/null @@ -1,96 +0,0 @@ -package services - -import ( - "io" - "testing" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/keypair" - "github.com/stellar/go/toid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var ( - checkpointMgr = historyarchive.NewCheckpointManager(0) -) - -func TestAccountTransactionCursorManager(t *testing.T) { - freq := int32(checkpointMgr.GetCheckpointFrequency()) - accountId := keypair.MustRandom().Address() - - // Create an index and fill it with some checkpoint details. - tmp := t.TempDir() - store, err := index.NewFileStore(tmp, - index.StoreConfig{ - URL: "file://" + tmp, - Workers: 4, - }, - ) - require.NoError(t, err) - - for _, checkpoint := range []uint32{1, 5, 10, 12} { - require.NoError(t, store.AddParticipantsToIndexes( - checkpoint, allTransactionsIndex, []string{accountId})) - } - - cursorMgr := NewCursorManagerForAccountActivity(store, accountId) - - cursor := toid.New(1, 1, 1) - var nextCursor int64 - - // first checkpoint works - nextCursor, err = cursorMgr.Begin(cursor.ToInt64()) - require.NoError(t, err) - assert.EqualValues(t, 1, getLedgerFromCursor(nextCursor)) - - // cursor is preserved if mid-active-range - cursor.LedgerSequence = freq / 2 - nextCursor, err = cursorMgr.Begin(cursor.ToInt64()) - require.NoError(t, err) - assert.EqualValues(t, cursor.LedgerSequence, getLedgerFromCursor(nextCursor)) - - // cursor jumps ahead if not active - cursor.LedgerSequence = 2 * freq - nextCursor, err = cursorMgr.Begin(cursor.ToInt64()) - require.NoError(t, err) - assert.EqualValues(t, 4*freq, getLedgerFromCursor(nextCursor)) - - // cursor increments - for i := int32(1); i < freq; i++ { - nextCursor, err = cursorMgr.Advance(1) - require.NoError(t, err) - assert.EqualValues(t, 4*freq+i, getLedgerFromCursor(nextCursor)) - } - - // cursor jumps to next active checkpoint - nextCursor, err = cursorMgr.Advance(1) - require.NoError(t, err) - assert.EqualValues(t, 9*freq, getLedgerFromCursor(nextCursor)) - - // cursor skips - nextCursor, err = cursorMgr.Advance(5) - require.NoError(t, err) - assert.EqualValues(t, 9*freq+5, getLedgerFromCursor(nextCursor)) - - // cursor jumps to next active when skipping - nextCursor, err = cursorMgr.Advance(uint(freq - 5)) - require.NoError(t, err) - assert.EqualValues(t, 11*freq, getLedgerFromCursor(nextCursor)) - - // cursor EOFs at the end - nextCursor, err = cursorMgr.Advance(uint(freq - 1)) - require.NoError(t, err) - assert.EqualValues(t, 12*freq-1, getLedgerFromCursor(nextCursor)) - _, err = cursorMgr.Advance(1) - assert.ErrorIs(t, err, io.EOF) - - // cursor EOFs if skipping past the end - rewind := toid.New(int32(getLedgerFromCursor(nextCursor)-5), 0, 0) - nextCursor, err = cursorMgr.Begin(rewind.ToInt64()) - require.NoError(t, err) - assert.EqualValues(t, rewind.LedgerSequence, getLedgerFromCursor(nextCursor)) - _, err = cursorMgr.Advance(uint(freq)) - assert.ErrorIs(t, err, io.EOF) -} diff --git a/exp/lighthorizon/services/main.go b/exp/lighthorizon/services/main.go deleted file mode 100644 index d391fc8baf..0000000000 --- a/exp/lighthorizon/services/main.go +++ /dev/null @@ -1,216 +0,0 @@ -package services - -import ( - "context" - "io" - "time" - - "github.com/prometheus/client_golang/prometheus" - "golang.org/x/exp/constraints" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -const ( - allTransactionsIndex = "all/all" - allPaymentsIndex = "all/payments" - slowFetchDurationThreshold = time.Second -) - -var ( - checkpointManager = historyarchive.NewCheckpointManager(0) -) - -// NewMetrics returns a Metrics instance containing all the prometheus -// metrics necessary for running light horizon services. -func NewMetrics(registry *prometheus.Registry) Metrics { - const minute = 60 - const day = 24 * 60 * minute - responseAgeHistogram := prometheus.NewHistogramVec(prometheus.HistogramOpts{ - Namespace: "horizon_lite", - Subsystem: "services", - Name: "response_age", - Buckets: []float64{ - 5 * minute, - 60 * minute, - day, - 7 * day, - 30 * day, - 90 * day, - 180 * day, - 365 * day, - }, - Help: "Age of the response for each service, sliding window = 10m", - }, - []string{"request", "successful"}, - ) - registry.MustRegister(responseAgeHistogram) - return Metrics{ - ResponseAgeHistogram: responseAgeHistogram, - } -} - -type LightHorizon struct { - Operations OperationService - Transactions TransactionService -} - -type Metrics struct { - ResponseAgeHistogram *prometheus.HistogramVec -} - -type Config struct { - Ingester ingester.Ingester - IndexStore index.Store - Passphrase string - Metrics Metrics -} - -// searchCallback is a generic way for any endpoint to process a transaction and -// its corresponding ledger. It should return whether or not we should stop -// processing (e.g. when a limit is reached) and any error that occurred. -type searchCallback func(ingester.LedgerTransaction, *xdr.LedgerHeader) (finished bool, err error) - -func searchAccountTransactions(ctx context.Context, - cursor int64, - accountId string, - config Config, - callback searchCallback, -) error { - cursorMgr := NewCursorManagerForAccountActivity(config.IndexStore, accountId) - cursor, err := cursorMgr.Begin(cursor) - if err == io.EOF { - return nil - } else if err != nil { - return err - } - nextLedger := getLedgerFromCursor(cursor) - - log.WithField("cursor", cursor). - Debugf("Searching %s for account %s starting at ledger %d", - allTransactionsIndex, accountId, nextLedger) - - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - fullStart := time.Now() - fetchDuration := time.Duration(0) - processDuration := time.Duration(0) - indexFetchDuration := time.Duration(0) - count := int64(0) - - defer func() { - log.WithField("ledgers", count). - WithField("ledger-fetch", fetchDuration). - WithField("ledger-process", processDuration). - WithField("index-fetch", indexFetchDuration). - WithField("avg-ledger-fetch", getAverageDuration(fetchDuration, count)). - WithField("avg-ledger-process", getAverageDuration(processDuration, count)). - WithField("avg-index-fetch", getAverageDuration(indexFetchDuration, count)). - WithField("total", time.Since(fullStart)). - Infof("Fulfilled request for account %s at cursor %d", accountId, cursor) - }() - - checkpointMgr := historyarchive.NewCheckpointManager(0) - - for { - if checkpointMgr.IsCheckpoint(nextLedger) { - r := historyarchive.Range{ - Low: nextLedger, - High: checkpointMgr.NextCheckpoint(nextLedger + 1), - } - log.Infof("Preparing ledger range [%d, %d]", r.Low, r.High) - if innerErr := config.Ingester.PrepareRange(ctx, r); innerErr != nil { - log.Errorf("failed to prepare ledger range [%d, %d]: %v", - r.Low, r.High, innerErr) - } - } - - start := time.Now() - ledger, innerErr := config.Ingester.GetLedger(ctx, nextLedger) - - // TODO: We should have helpful error messages when innerErr points to a - // 404 for that particular ledger, since that situation shouldn't happen - // under normal operations, but rather indicates a problem with the - // backing archive. - if innerErr != nil { - return errors.Wrapf(innerErr, - "failed to retrieve ledger %d from archive", nextLedger) - } - count++ - thisFetchDuration := time.Since(start) - if thisFetchDuration > slowFetchDurationThreshold { - log.WithField("duration", thisFetchDuration). - Warnf("Fetching ledger %d was really slow", nextLedger) - } - fetchDuration += thisFetchDuration - - start = time.Now() - reader, innerErr := config.Ingester.NewLedgerTransactionReader(ledger) - if innerErr != nil { - return errors.Wrapf(innerErr, - "failed to read ledger %d", nextLedger) - } - - for { - if ctx.Err() != nil { - return ctx.Err() - } - - tx, readErr := reader.Read() - if readErr == io.EOF { - break - } else if readErr != nil { - return readErr - } - - // Note: If we move to ledger-based indices, we don't need this, - // since we have a guarantee that the transaction will contain - // the account as a participant. - participants, participantErr := ingester.GetTransactionParticipants(tx) - if participantErr != nil { - return participantErr - } - - if _, found := participants[accountId]; found { - finished, callBackErr := callback(tx, &ledger.V0.V0.LedgerHeader.Header) - if callBackErr != nil { - return callBackErr - } else if finished { - processDuration += time.Since(start) - return nil - } - } - } - - processDuration += time.Since(start) - start = time.Now() - - cursor, err = cursorMgr.Advance(1) - if err != nil && err != io.EOF { - return err - } - - nextLedger = getLedgerFromCursor(cursor) - indexFetchDuration += time.Since(start) - if err == io.EOF { - break - } - } - - return nil -} - -func getAverageDuration[ - T constraints.Signed | constraints.Float, -](d time.Duration, count T) time.Duration { - if count == 0 { - return 0 // don't bomb on div-by-zero - } - return time.Duration(int64(float64(d.Nanoseconds()) / float64(count))) -} diff --git a/exp/lighthorizon/services/main_test.go b/exp/lighthorizon/services/main_test.go deleted file mode 100644 index a8a3958214..0000000000 --- a/exp/lighthorizon/services/main_test.go +++ /dev/null @@ -1,250 +0,0 @@ -package services - -import ( - "context" - "io" - "testing" - - "github.com/prometheus/client_golang/prometheus" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/ingest" - "github.com/stellar/go/toid" - "github.com/stellar/go/xdr" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" -) - -var ( - passphrase = "White New England clam chowder" - accountId = "GDCXSQPVE45DVGT2ZRFFIIHSJ2EJED65W6AELGWIDRMPMWNXCEBJ4FKX" - startLedgerSeq = 1586112 -) - -func TestItGetsTransactionsByAccount(t *testing.T) { - ctx := context.Background() - - // this is in the checkpoint range prior to the first active checkpoint - ledgerSeq := checkpointMgr.PrevCheckpoint(uint32(startLedgerSeq)) - cursor := toid.New(int32(ledgerSeq), 1, 1).ToInt64() - - t.Run("first", func(tt *testing.T) { - txService := newTransactionService(ctx) - - txs, err := txService.GetTransactionsByAccount(ctx, cursor, 1, accountId) - require.NoError(tt, err) - require.Len(tt, txs, 1) - require.Equal(tt, txs[0].LedgerHeader.LedgerSeq, xdr.Uint32(1586113)) - require.EqualValues(tt, txs[0].TxIndex, 2) - }) - - t.Run("without cursor", func(tt *testing.T) { - txService := newTransactionService(ctx) - - txs, err := txService.GetTransactionsByAccount(ctx, 0, 1, accountId) - require.NoError(tt, err) - require.Len(tt, txs, 1) - require.Equal(tt, txs[0].LedgerHeader.LedgerSeq, xdr.Uint32(1586113)) - require.EqualValues(tt, txs[0].TxIndex, 2) - }) - - t.Run("with limit", func(tt *testing.T) { - txService := newTransactionService(ctx) - - txs, err := txService.GetTransactionsByAccount(ctx, cursor, 5, accountId) - require.NoError(tt, err) - require.Len(tt, txs, 2) - require.Equal(tt, txs[0].LedgerHeader.LedgerSeq, xdr.Uint32(1586113)) - require.EqualValues(tt, txs[0].TxIndex, 2) - require.Equal(tt, txs[1].LedgerHeader.LedgerSeq, xdr.Uint32(1586114)) - require.EqualValues(tt, txs[1].TxIndex, 1) - }) -} - -func TestItGetsOperationsByAccount(t *testing.T) { - ctx := context.Background() - - // this is in the checkpoint range prior to the first active checkpoint - ledgerSeq := checkpointMgr.PrevCheckpoint(uint32(startLedgerSeq)) - cursor := toid.New(int32(ledgerSeq), 1, 1).ToInt64() - - t.Run("first", func(tt *testing.T) { - opsService := newOperationService(ctx) - - // this should start at next checkpoint - ops, err := opsService.GetOperationsByAccount(ctx, cursor, 1, accountId) - require.NoError(tt, err) - require.Len(tt, ops, 1) - require.Equal(tt, ops[0].LedgerHeader.LedgerSeq, xdr.Uint32(1586113)) - require.Equal(tt, ops[0].TxIndex, int32(2)) - - }) - - t.Run("with limit", func(tt *testing.T) { - opsService := newOperationService(ctx) - - // this should start at next checkpoint - ops, err := opsService.GetOperationsByAccount(ctx, cursor, 5, accountId) - require.NoError(tt, err) - require.Len(tt, ops, 2) - require.Equal(tt, ops[0].LedgerHeader.LedgerSeq, xdr.Uint32(1586113)) - require.Equal(tt, ops[0].TxIndex, int32(2)) - require.Equal(tt, ops[1].LedgerHeader.LedgerSeq, xdr.Uint32(1586114)) - require.Equal(tt, ops[1].TxIndex, int32(1)) - }) -} - -func mockArchiveAndIndex(ctx context.Context) (ingester.Ingester, index.Store) { - mockArchive := &ingester.MockIngester{} - mockReaderLedger1 := &ingester.MockLedgerTransactionReader{} - mockReaderLedger2 := &ingester.MockLedgerTransactionReader{} - mockReaderLedger3 := &ingester.MockLedgerTransactionReader{} - mockReaderLedgerTheRest := &ingester.MockLedgerTransactionReader{} - - expectedLedger1 := testLedger(startLedgerSeq) - expectedLedger2 := testLedger(startLedgerSeq + 1) - expectedLedger3 := testLedger(startLedgerSeq + 2) - - // throw an irrelevant account in there to make sure it's filtered - source := xdr.MustAddress("GCXKG6RN4ONIEPCMNFB732A436Z5PNDSRLGWK7GBLCMQLIFO4S7EYWVU") - source2 := xdr.MustAddress(accountId) - - // assert results iterate sequentially across ops-tx-ledgers - expectedLedger1Tx1 := testLedgerTx(source, 1, 34, 35) - expectedLedger1Tx2 := testLedgerTx(source, 2, 34) - expectedLedger2Tx1 := testLedgerTx(source, 1, 34) - expectedLedger2Tx2 := testLedgerTx(source2, 2, 34) - expectedLedger3Tx1 := testLedgerTx(source2, 1, 34) - expectedLedger3Tx2 := testLedgerTx(source, 2, 34) - - mockReaderLedger1. - On("Read").Return(expectedLedger1Tx1, nil).Once(). - On("Read").Return(expectedLedger1Tx2, nil).Once(). - On("Read").Return(ingester.LedgerTransaction{}, io.EOF).Once() - - mockReaderLedger2. - On("Read").Return(expectedLedger2Tx1, nil).Once(). - On("Read").Return(expectedLedger2Tx2, nil).Once(). - On("Read").Return(ingester.LedgerTransaction{}, io.EOF).Once() - - mockReaderLedger3. - On("Read").Return(expectedLedger3Tx1, nil).Once(). - On("Read").Return(expectedLedger3Tx2, nil).Once(). - On("Read").Return(ingester.LedgerTransaction{}, io.EOF).Once() - - mockReaderLedgerTheRest. - On("Read").Return(ingester.LedgerTransaction{}, io.EOF) - - mockArchive. - On("GetLedger", mock.Anything, uint32(1586112)).Return(expectedLedger1, nil). - On("GetLedger", mock.Anything, uint32(1586113)).Return(expectedLedger2, nil). - On("GetLedger", mock.Anything, uint32(1586114)).Return(expectedLedger3, nil). - On("GetLedger", mock.Anything, mock.AnythingOfType("uint32")). - Return(xdr.SerializedLedgerCloseMeta{}, nil) - - mockArchive. - On("NewLedgerTransactionReader", expectedLedger1).Return(mockReaderLedger1, nil).Once(). - On("NewLedgerTransactionReader", expectedLedger2).Return(mockReaderLedger2, nil).Once(). - On("NewLedgerTransactionReader", expectedLedger3).Return(mockReaderLedger3, nil).Once(). - On("NewLedgerTransactionReader", mock.AnythingOfType("xdr.SerializedLedgerCloseMeta")). - Return(mockReaderLedgerTheRest, nil). - On("PrepareRange", mock.Anything, mock.Anything).Return(nil) - - // should be 24784 - activeChk := uint32(index.GetCheckpointNumber(uint32(startLedgerSeq))) - mockStore := &index.MockStore{} - mockStore. - On("NextActive", accountId, mock.Anything, uint32(0)).Return(activeChk, nil). // start - On("NextActive", accountId, mock.Anything, activeChk-1).Return(activeChk, nil). // prev - On("NextActive", accountId, mock.Anything, activeChk).Return(activeChk, nil). // curr - On("NextActive", accountId, mock.Anything, activeChk+1).Return(uint32(0), io.EOF) // next - - return mockArchive, mockStore -} - -func testLedger(seq int) xdr.SerializedLedgerCloseMeta { - return xdr.SerializedLedgerCloseMeta{ - V: 0, - V0: &xdr.LedgerCloseMeta{ - V0: &xdr.LedgerCloseMetaV0{ - LedgerHeader: xdr.LedgerHeaderHistoryEntry{ - Header: xdr.LedgerHeader{ - LedgerSeq: xdr.Uint32(seq), - }, - }, - }, - }, - } -} - -func testLedgerTx(source xdr.AccountId, txIndex uint32, bumpTos ...int) ingester.LedgerTransaction { - code := xdr.TransactionResultCodeTxSuccess - - operations := []xdr.Operation{} - for _, bumpTo := range bumpTos { - operations = append(operations, xdr.Operation{ - Body: xdr.OperationBody{ - Type: xdr.OperationTypeBumpSequence, - BumpSequenceOp: &xdr.BumpSequenceOp{ - BumpTo: xdr.SequenceNumber(bumpTo), - }, - }, - }) - } - - return ingester.LedgerTransaction{ - LedgerTransaction: &ingest.LedgerTransaction{ - Result: xdr.TransactionResultPair{ - TransactionHash: xdr.Hash{}, - Result: xdr.TransactionResult{ - Result: xdr.TransactionResultResult{ - Code: code, - InnerResultPair: &xdr.InnerTransactionResultPair{}, - Results: &[]xdr.OperationResult{}, - }, - }, - }, - Envelope: xdr.TransactionEnvelope{ - Type: xdr.EnvelopeTypeEnvelopeTypeTx, - V1: &xdr.TransactionV1Envelope{ - Tx: xdr.Transaction{ - SourceAccount: source.ToMuxedAccount(), - Operations: operations, - }, - }, - }, - UnsafeMeta: xdr.TransactionMeta{ - V: 2, - V2: &xdr.TransactionMetaV2{ - Operations: make([]xdr.OperationMeta, len(bumpTos)), - }, - }, - Index: txIndex, - }, - } -} - -func newTransactionService(ctx context.Context) TransactionService { - ingest, store := mockArchiveAndIndex(ctx) - return &TransactionRepository{ - Config: Config{ - Ingester: ingest, - IndexStore: store, - Passphrase: passphrase, - Metrics: NewMetrics(prometheus.NewRegistry()), - }, - } -} - -func newOperationService(ctx context.Context) OperationService { - ingest, store := mockArchiveAndIndex(ctx) - return &OperationRepository{ - Config: Config{ - Ingester: ingest, - IndexStore: store, - Passphrase: passphrase, - Metrics: NewMetrics(prometheus.NewRegistry()), - }, - } -} diff --git a/exp/lighthorizon/services/mock_services.go b/exp/lighthorizon/services/mock_services.go deleted file mode 100644 index be573489e0..0000000000 --- a/exp/lighthorizon/services/mock_services.go +++ /dev/null @@ -1,32 +0,0 @@ -package services - -import ( - "context" - - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stretchr/testify/mock" -) - -type MockTransactionService struct { - mock.Mock -} - -func (m *MockTransactionService) GetTransactionsByAccount(ctx context.Context, - cursor int64, limit uint64, - accountId string, -) ([]common.Transaction, error) { - args := m.Called(ctx, cursor, limit, accountId) - return args.Get(0).([]common.Transaction), args.Error(1) -} - -type MockOperationService struct { - mock.Mock -} - -func (m *MockOperationService) GetOperationsByAccount(ctx context.Context, - cursor int64, limit uint64, - accountId string, -) ([]common.Operation, error) { - args := m.Called(ctx, cursor, limit, accountId) - return args.Get(0).([]common.Operation), args.Error(1) -} diff --git a/exp/lighthorizon/services/operations.go b/exp/lighthorizon/services/operations.go deleted file mode 100644 index 1236bcdb01..0000000000 --- a/exp/lighthorizon/services/operations.go +++ /dev/null @@ -1,90 +0,0 @@ -package services - -import ( - "context" - "strconv" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -type OperationService interface { - GetOperationsByAccount(ctx context.Context, - cursor int64, limit uint64, - accountId string, - ) ([]common.Operation, error) -} - -type OperationRepository struct { - OperationService - Config Config -} - -func (or *OperationRepository) GetOperationsByAccount(ctx context.Context, - cursor int64, limit uint64, - accountId string, -) ([]common.Operation, error) { - ops := []common.Operation{} - - opsCallback := func(tx ingester.LedgerTransaction, ledgerHeader *xdr.LedgerHeader) (bool, error) { - for operationOrder, op := range tx.Envelope.Operations() { - opParticipants, err := ingester.GetOperationParticipants(tx, op, operationOrder) - if err != nil { - return false, err - } - - if _, foundInOp := opParticipants[accountId]; foundInOp { - ops = append(ops, common.Operation{ - TransactionEnvelope: &tx.Envelope, - TransactionResult: &tx.Result.Result, - LedgerHeader: ledgerHeader, - TxIndex: int32(tx.Index), - OpIndex: int32(operationOrder), - }) - - if uint64(len(ops)) == limit { - return true, nil - } - } - } - - return false, nil - } - - err := searchAccountTransactions(ctx, cursor, accountId, or.Config, opsCallback) - if age := operationsResponseAgeSeconds(ops); age >= 0 { - or.Config.Metrics.ResponseAgeHistogram.With(prometheus.Labels{ - "request": "GetOperationsByAccount", - "successful": strconv.FormatBool(err == nil), - }).Observe(age) - } - - return ops, err -} - -func operationsResponseAgeSeconds(ops []common.Operation) float64 { - if len(ops) == 0 { - return -1 - } - - oldest := ops[0].LedgerHeader.ScpValue.CloseTime - for i := 1; i < len(ops); i++ { - if closeTime := ops[i].LedgerHeader.ScpValue.CloseTime; closeTime < oldest { - oldest = closeTime - } - } - - lastCloseTime := time.Unix(int64(oldest), 0).UTC() - now := time.Now().UTC() - if now.Before(lastCloseTime) { - log.Errorf("current time %v is before oldest operation close time %v", now, lastCloseTime) - return -1 - } - return now.Sub(lastCloseTime).Seconds() -} - -var _ OperationService = (*OperationRepository)(nil) // ensure conformity to the interface diff --git a/exp/lighthorizon/services/transactions.go b/exp/lighthorizon/services/transactions.go deleted file mode 100644 index 42d3964614..0000000000 --- a/exp/lighthorizon/services/transactions.go +++ /dev/null @@ -1,76 +0,0 @@ -package services - -import ( - "context" - "strconv" - "time" - - "github.com/prometheus/client_golang/prometheus" - "github.com/stellar/go/exp/lighthorizon/common" - "github.com/stellar/go/exp/lighthorizon/ingester" - "github.com/stellar/go/support/log" - "github.com/stellar/go/xdr" -) - -type TransactionRepository struct { - TransactionService - Config Config -} - -type TransactionService interface { - GetTransactionsByAccount(ctx context.Context, - cursor int64, limit uint64, - accountId string, - ) ([]common.Transaction, error) -} - -func (tr *TransactionRepository) GetTransactionsByAccount(ctx context.Context, - cursor int64, limit uint64, - accountId string, -) ([]common.Transaction, error) { - txs := []common.Transaction{} - - txsCallback := func(tx ingester.LedgerTransaction, ledgerHeader *xdr.LedgerHeader) (bool, error) { - txs = append(txs, common.Transaction{ - LedgerTransaction: &tx, - LedgerHeader: ledgerHeader, - TxIndex: int32(tx.Index), - NetworkPassphrase: tr.Config.Passphrase, - }) - - return uint64(len(txs)) == limit, nil - } - - err := searchAccountTransactions(ctx, cursor, accountId, tr.Config, txsCallback) - if age := transactionsResponseAgeSeconds(txs); age >= 0 { - tr.Config.Metrics.ResponseAgeHistogram.With(prometheus.Labels{ - "request": "GetTransactionsByAccount", - "successful": strconv.FormatBool(err == nil), - }).Observe(age) - } - - return txs, err -} - -func transactionsResponseAgeSeconds(txs []common.Transaction) float64 { - if len(txs) == 0 { - return -1 - } - - oldest := txs[0].LedgerHeader.ScpValue.CloseTime - for i := 1; i < len(txs); i++ { - if closeTime := txs[i].LedgerHeader.ScpValue.CloseTime; closeTime < oldest { - oldest = closeTime - } - } - - lastCloseTime := time.Unix(int64(oldest), 0).UTC() - now := time.Now().UTC() - if now.Before(lastCloseTime) { - log.Errorf("current time %v is before oldest transaction close time %v", now, lastCloseTime) - return -1 - } - return now.Sub(lastCloseTime).Seconds() -} - -var _ TransactionService = (*TransactionRepository)(nil) // ensure conformity to the interface diff --git a/exp/lighthorizon/tools/cache.go b/exp/lighthorizon/tools/cache.go deleted file mode 100644 index 0290fcb164..0000000000 --- a/exp/lighthorizon/tools/cache.go +++ /dev/null @@ -1,270 +0,0 @@ -package tools - -import ( - "context" - "fmt" - "io/ioutil" - "os" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/spf13/cobra" - - "github.com/stellar/go/metaarchive" - "github.com/stellar/go/support/log" - "github.com/stellar/go/support/storage" -) - -const ( - defaultCacheCount = (60 * 60 * 24) / 5 // ~24hrs worth of ledgers -) - -func AddCacheCommands(parent *cobra.Command) *cobra.Command { - cmd := &cobra.Command{ - Use: "cache", - Long: "Manages the on-disk cache of ledgers.", - Example: ` -cache build --start 1234 --count 1000 s3://txmeta /tmp/example -cache purge /tmp/example 1234 1300 -cache show /tmp/example`, - RunE: func(cmd *cobra.Command, args []string) error { - // require a subcommand - this is just a "category" - return cmd.Help() - }, - } - - purge := &cobra.Command{ - Use: "purge [flags] path ", - Long: "Purges individual ledgers (or ranges) from the cache, or the entire cache.", - Example: ` -purge /tmp/example # empty the whole cache -purge /tmp/example 1000 # purge one ledger -purge /tmp/example 1000 1005 # purge a ledger range`, - RunE: func(cmd *cobra.Command, args []string) error { - // The first parameter must be a valid cache directory. - // You can then pass nothing, a single ledger, or a ledger range. - if len(args) < 1 || len(args) > 3 { - return cmd.Usage() - } - - var err error - var start, end uint64 - if len(args) > 1 { - start, err = strconv.ParseUint(args[1], 10, 32) - if err != nil { - cmd.Printf("Error: '%s' not a ledger sequence: %v\n", args[1], err) - return cmd.Usage() - } - } - end = start // fallback - - if len(args) == 3 { - end, err = strconv.ParseUint(args[2], 10, 32) - if err != nil { - cmd.Printf("Error: '%s' not a ledger sequence: %v\n", args[2], err) - return cmd.Usage() - } else if end < start { - cmd.Printf("Error: end precedes start (%d < %d)\n", end, start) - return cmd.Usage() - } - } - - path := args[0] - if start > 0 { - return PurgeLedgers(path, uint32(start), uint32(end)) - } - return PurgeCache(path) - }, - } - show := &cobra.Command{ - Use: "show ", - Long: "Traverses the on-disk cache and prints out cached ledger ranges.", - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return cmd.Usage() - } - return ShowCache(args[0]) - }, - } - build := &cobra.Command{ - Use: "build [flags] ", - Example: "See cache --help text", - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 2 { - cmd.Println("Error: 2 positional arguments are required") - return cmd.Usage() - } - - start, err := cmd.Flags().GetUint32("start") - if err != nil || start < 2 { - cmd.Println("--start is required to be a ledger sequence") - return cmd.Usage() - } - - count, err := cmd.Flags().GetUint32("count") - if err != nil || count <= 0 { - cmd.Println("--count should be a positive 32-bit integer") - return cmd.Usage() - } - repair, _ := cmd.Flags().GetBool("repair") - return BuildCache(args[0], args[1], start, count, repair) - }, - } - - build.Flags().Bool("repair", false, "attempt to purge the cache and retry ledgers that error") - build.Flags().Uint32("start", 0, "first ledger to cache (required)") - build.Flags().Uint32("count", defaultCacheCount, "number of ledgers to cache") - - cmd.AddCommand(build, purge, show) - if parent == nil { - return cmd - } - - parent.AddCommand(cmd) - return parent -} - -func BuildCache(ledgerSource, cacheDir string, start uint32, count uint32, repair bool) error { - fullStart := time.Now() - L := log.DefaultLogger - L.SetLevel(log.InfoLevel) - log := L - - ctx := context.Background() - store, err := storage.ConnectBackend(ledgerSource, storage.ConnectOptions{ - Context: ctx, - Wrap: func(store storage.Storage) (storage.Storage, error) { - return storage.MakeOnDiskCache(store, cacheDir, uint(count)) - }, - }) - if err != nil { - log.Errorf("Couldn't create local cache for '%s' at '%s': %v", - ledgerSource, cacheDir, err) - return err - } - - log.Infof("Connected to ledger source at %s", ledgerSource) - log.Infof("Connected to ledger cache at %s", cacheDir) - - source := metaarchive.NewMetaArchive(store) - log.Infof("Filling local cache of ledgers at %s...", cacheDir) - log.Infof("Ledger range: [%d, %d] (%d ledgers)", - start, start+count-1, count) - - successful := uint(0) - for i := uint32(0); i < count; i++ { - ledgerSeq := start + uint32(i) - - // do "best effort" caching, skipping if too slow - dlCtx, dlCancel := context.WithTimeout(ctx, 10*time.Second) - start := time.Now() - - _, err := source.GetLedger(dlCtx, ledgerSeq) // this caches - dlCancel() - - if err != nil { - if repair && strings.Contains(err.Error(), "xdr") { - log.Warnf("Caching ledger %d failed, purging & retrying: %v", ledgerSeq, err) - store.(*storage.OnDiskCache).Evict(fmt.Sprintf("ledgers/%d", ledgerSeq)) - i-- // retry - } else { - log.Warnf("Caching ledger %d failed, skipping: %v", ledgerSeq, err) - log.Warn("If you see an XDR decoding error, the cache may be corrupted.") - log.Warnf("Run '%s purge %d' and try again, or pass --repair", - filepath.Base(os.Args[0]), ledgerSeq) - } - continue - } else { - successful++ - } - - duration := time.Since(start) - if duration > 2*time.Second { - log.WithField("duration", duration). - Warnf("Downloading ledger %d took a while.", ledgerSeq) - } - - log = log.WithField("failures", 1+uint(i)-successful) - if successful%97 == 0 { - log.Infof("Cached %d/%d ledgers (%0.1f%%)", successful, count, - 100*float64(successful)/float64(count)) - } - } - - duration := time.Since(fullStart) - log.WithField("duration", duration). - Infof("Cached %d ledgers into %s", successful, cacheDir) - - return nil -} - -func PurgeLedgers(cacheDir string, start, end uint32) error { - base := filepath.Join(cacheDir, "ledgers") - - successful := 0 - for i := start; i <= end; i++ { - ledgerPath := filepath.Join(base, strconv.FormatUint(uint64(i), 10)) - if err := os.Remove(ledgerPath); err != nil { - log.Warnf("Failed to remove cached ledger %d: %v", i, err) - continue - } - os.Remove(storage.NameLockfile(ledgerPath)) // ignore lockfile errors - log.Debugf("Purged ledger from %s", ledgerPath) - successful++ - } - - log.Infof("Purged %d cached ledgers from %s", successful, cacheDir) - return nil -} - -func PurgeCache(cacheDir string) error { - if err := os.RemoveAll(cacheDir); err != nil { - log.Warnf("Failed to remove cache directory (%s): %v", cacheDir, err) - return err - } - - log.Infof("Purged cache at %s", cacheDir) - return nil -} - -func ShowCache(cacheDir string) error { - files, err := ioutil.ReadDir(filepath.Join(cacheDir, "ledgers")) - if err != nil { - log.Errorf("Failed to read cache: %v", err) - return err - } - - ledgers := make([]uint32, 0, len(files)) - - for _, f := range files { - if f.IsDir() { - continue - } - - // If the name can be converted to a ledger sequence, track it. - if seq, errr := strconv.ParseUint(f.Name(), 10, 32); errr == nil { - ledgers = append(ledgers, uint32(seq)) - } - } - - log.Infof("Analyzed cache at %s: %d cached ledgers.", cacheDir, len(ledgers)) - if len(ledgers) == 0 { - return nil - } - - // Find consecutive ranges of ledgers in the cache - log.Infof("Cached ranges:") - firstSeq, lastSeq := ledgers[0], ledgers[0] - for i := 1; i < len(ledgers); i++ { - if ledgers[i]-1 != lastSeq { - log.Infof(" - [%d, %d]", firstSeq, lastSeq) - firstSeq = ledgers[i] - } - lastSeq = ledgers[i] - } - - log.Infof(" - [%d, %d]", firstSeq, lastSeq) - return nil -} diff --git a/exp/lighthorizon/tools/index.go b/exp/lighthorizon/tools/index.go deleted file mode 100644 index e37a7eb38a..0000000000 --- a/exp/lighthorizon/tools/index.go +++ /dev/null @@ -1,356 +0,0 @@ -package tools - -import ( - "context" - "io" - "os" - "os/signal" - "strconv" - "strings" - "syscall" - "time" - - "github.com/spf13/cobra" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/strkey" - "github.com/stellar/go/support/collections/maps" - "github.com/stellar/go/support/collections/set" - "github.com/stellar/go/support/log" - "github.com/stellar/go/support/ordered" -) - -var ( - checkpointMgr = historyarchive.NewCheckpointManager(0) -) - -func AddIndexCommands(parent *cobra.Command) *cobra.Command { - cmd := &cobra.Command{ - Use: "index", - Long: "Lets you view details about an index source and modify it.", - Example: ` -index view file:///tmp/indices -index view file:///tmp/indices GAGJZWQ5QT34VK3U6W6YKRYFIK6YSAXQC6BHIIYLG6X3CE5QW2KAYNJR -index stats file:///tmp/indices`, - RunE: func(cmd *cobra.Command, args []string) error { - // require a subcommand - this is just a "category" - return cmd.Help() - }, - } - - stats := &cobra.Command{ - Use: "stats ", - Long: "Summarize the statistics (like the # of active checkpoints " + - "or accounts). Note that this is a very read-heavy operation and " + - "will incur download bandwidth costs if reading from remote, " + - "billable sources.", - Example: `stats s3://indices`, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 1 { - return cmd.Usage() - } - - path := args[0] - start := time.Now() - log.Infof("Analyzing indices at %s", path) - - allCheckpoints := set.Set[uint32]{} - allIndexNames := set.Set[string]{} - accounts := showAccounts(path, 0) - log.Infof("Analyzing indices for %d accounts.", len(accounts)) - - // We want to summarize as much as possible on a Ctrl+C event, so - // this handles that by setting up a context that gets cancelled on - // SIGINT. A second Ctrl+C will kill the process as usual. - // - // https://millhouse.dev/posts/graceful-shutdowns-in-golang-with-signal-notify-context - ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, syscall.SIGINT) - defer stop() - go func() { - <-ctx.Done() - stop() - log.WithField("error", ctx.Err()). - Warn("Received interrupt, shutting down gracefully & summarizing findings...") - log.Warn("Press Ctrl+C again to abort.") - }() - - mostActiveAccountChk := 0 - mostActiveAccount := "" - for _, account := range accounts { - if ctx.Err() != nil { - break - } - - activity := getIndex(path, account, "", 0) - allCheckpoints.AddSlice(maps.Keys(activity)) - for _, names := range activity { - allIndexNames.AddSlice(names) - } - - if len(activity) > mostActiveAccountChk { - mostActiveAccount = account - mostActiveAccountChk = len(activity) - } - } - - ledgerCount := len(allCheckpoints) * int(checkpointMgr.GetCheckpointFrequency()) - - log.Info("Done analyzing indices, summarizing...") - log.Infof("") - log.Infof("=== Final Summary ===") - log.Infof("Analysis took %s.", time.Since(start)) - log.Infof("Path: %s", path) - log.Infof("Accounts: %d", len(accounts)) - log.Infof("Smallest checkpoint: %d", ordered.MinSlice(allCheckpoints.Slice())) - log.Infof("Largest checkpoint: %d", ordered.MaxSlice(allCheckpoints.Slice())) - log.Infof("Checkpoint count: %d (%d possible ledgers, ~%0.2f days)", - len(allCheckpoints), ledgerCount, - float64(ledgerCount)/(float64(60*60*24)/6.0) /* approx. ledgers per day */) - log.Infof("Index names: %s", strings.Join(allIndexNames.Slice(), ", ")) - log.Infof("Most active account: %s (%d checkpoints)", - mostActiveAccount, mostActiveAccountChk) - - return nil - }, - } - - view := &cobra.Command{ - Use: "view [accounts?]", - Long: "View the accounts in an index source or view the " + - "checkpoints specific account(s) are active in.", - Example: `view s3://indices -view s3:///indices GAXLQGKIUAIIUHAX4GJO3J7HFGLBCNF6ZCZSTLJE7EKO5IUHGLQLMXZO -view file:///tmp/indices --limit=0 GAXLQGKIUAIIUHAX4GJO3J7HFGLBCNF6ZCZSTLJE7EKO5IUHGLQLMXZO -view gcs://indices --limit=10 GAXLQGKIUAIIUHAX4GJO3J7HFGLBCNF6ZCZSTLJE7EKO5IUHGLQLMXZO,GBUUWQDVEEXBJCUF5UL24YGXKJIP5EMM7KFWIAR33KQRJR34GN6HEDPV,GBYETUYNBK2ZO5MSYBJKSLDEA2ZHIXLCFL3MMWU6RHFVAUBKEWQORYKS`, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 || len(args) > 2 { - return cmd.Usage() - } - - path := args[0] - log.Infof("Analyzing indices at %s", path) - - accounts := []string{} - if len(args) == 2 { - accounts = strings.Split(args[1], ",") - } - - limit, err := cmd.Flags().GetUint("limit") - if err != nil { - return cmd.Usage() - } - - if len(accounts) > 0 { - indexName, err := cmd.Flags().GetString("index-name") - if err != nil { - return cmd.Usage() - } - - for _, account := range accounts { - if !strkey.IsValidEd25519PublicKey(account) && - !strkey.IsValidMuxedAccountEd25519PublicKey(account) { - log.Errorf("Invalid account ID: '%s'", account) - continue - } - - getIndex(path, account, indexName, limit) - } - } else { - showAccounts(path, limit) - } - - return nil - }, - } - - purge := &cobra.Command{ - Use: "purge ", - Long: "Purges all indices for the given ledger range.", - Example: `purge s3://indices 10000 10005`, - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) != 3 { - return cmd.Usage() - } - - path := args[0] - start, err := strconv.ParseUint(args[1], 10, 32) - if err != nil { - return cmd.Usage() - } - end, err := strconv.ParseUint(args[2], 10, 32) - if err != nil { - return cmd.Usage() - } - - r := historyarchive.Range{Low: uint32(start), High: uint32(end)} - log.Infof("Purging all indices from %s for ledger range: [%d, %d].", - path, r.Low, r.High) - - return purgeIndex(path, r) - }, - } - - view.Flags().Uint("limit", 10, "a maximum number of accounts or checkpoints to show") - view.Flags().String("index-name", "", "filter for a particular index") - cmd.AddCommand(stats, view, purge) - - if parent == nil { - return cmd - } - parent.AddCommand(cmd) - return parent -} - -func getIndex(path, account, indexName string, limit uint) map[uint32][]string { - freq := checkpointMgr.GetCheckpointFrequency() - - store, err := index.Connect(path) - if err != nil { - log.Fatalf("Failed to connect to index store at %s: %v", path, err) - return nil - } - - indices, err := store.Read(account) - if err != nil { - log.Fatalf("Failed to read indices for %s from index store at %s: %v", - account, path, err) - return nil - } - - // It's better to summarize activity and then group it by index rather than - // just show activity in each index, because there's likely a ton of overlap - // across indices. - activity := map[uint32][]string{} - indexNames := []string{} - - for name, idx := range indices { - log.Infof("Index found: '%s'", name) - if indexName != "" && name != indexName { - continue - } - - indexNames = append(indexNames, name) - - checkpoint, err := idx.NextActiveBit(0) - for err != io.EOF { - activity[checkpoint] = append(activity[checkpoint], name) - checkpoint, err = idx.NextActiveBit(checkpoint + 1) - - if limit > 0 && limit <= uint(len(activity)) { - break - } - } - } - - log.WithField("account", account).WithField("limit", limit). - Infof("Activity for account:") - - for checkpoint, names := range activity { - first := (checkpoint - 1) * freq - last := first + freq - - nameStr := strings.Join(names, ", ") - log.WithField("indices", nameStr). - Infof(" - checkpoint %d, ledgers [%d, %d)", checkpoint, first, last) - } - - log.Infof("Summary: %d active checkpoints, %d possible active ledgers", - len(activity), len(activity)*int(freq)) - log.Infof("Checkpoint range: [%d, %d]", - ordered.MinSlice(maps.Keys(activity)), - ordered.MaxSlice(maps.Keys(activity))) - log.Infof("All discovered indices: %s", strings.Join(indexNames, ", ")) - - return activity -} - -func showAccounts(path string, limit uint) []string { - store, err := index.Connect(path) - if err != nil { - log.Fatalf("Failed to connect to index store at %s: %v", path, err) - return nil - } - - accounts, err := store.ReadAccounts() - if err != nil { - log.Fatalf("Failed read accounts from index store at %s: %v", path, err) - return nil - } - - if limit == 0 { - limit = uint(len(accounts)) - } - - for i := uint(0); i < limit; i++ { - log.Info(accounts[i]) - } - - return accounts -} - -func purgeIndex(path string, r historyarchive.Range) error { - freq := historyarchive.DefaultCheckpointFrequency - store, err := index.Connect(path) - if err != nil { - log.Fatalf("Failed to connect to index store at %s: %v", path, err) - return err - } - - accounts, err := store.ReadAccounts() - if err != nil { - log.Fatalf("Failed read accounts: %v", err) - return err - } - - purged := 0 - for _, account := range accounts { - L := log.WithField("account", account) - - indices, err := store.Read(account) - if err != nil { - L.Errorf("Failed to read indices: %v", err) - continue - } - - for name, index := range indices { - var err error - active := uint32(0) - for err == nil { - if active*freq < r.Low { // too low, skip ahead - active, err = index.NextActiveBit(active + 1) - continue - } else if active*freq > r.High { // too high, we're done - break - } - - L.WithField("index", name). - Debugf("Purged checkpoint %d (ledgers %d through %d).", - active, active*freq, (active+1)*freq-1) - - purged++ - - index.SetInactive(active) - active, err = index.NextActiveBit(active) - } - - if err != nil && err != io.EOF { - L.WithField("index", name). - Errorf("Iterating over index failed: %v", err) - continue - } - - } - - store.AddParticipantToIndexesNoBackend(account, indices) - if err := store.Flush(); err != nil { - log.WithField("account", account). - Errorf("Flushing index failed: %v", err) - continue - } - } - - log.Infof("Purged %d values across %d accounts from all indices at %s.", - purged, len(accounts), path) - return nil -} diff --git a/exp/lighthorizon/tools/index_test.go b/exp/lighthorizon/tools/index_test.go deleted file mode 100644 index 6d42f88f30..0000000000 --- a/exp/lighthorizon/tools/index_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package tools - -import ( - "path/filepath" - "testing" - - "github.com/stellar/go/exp/lighthorizon/index" - "github.com/stellar/go/historyarchive" - "github.com/stellar/go/keypair" - "github.com/stellar/go/support/log" - "github.com/stretchr/testify/require" -) - -const ( - freq = historyarchive.DefaultCheckpointFrequency -) - -func TestIndexPurge(t *testing.T) { - log.SetLevel(log.DebugLevel) - - tempFile := "file://" + filepath.Join(t.TempDir(), "index-store") - accounts := []string{keypair.MustRandom().Address()} - - idx, err := index.Connect(tempFile) - require.NoError(t, err) - - for _, chk := range []uint32{14, 15, 16, 17, 20, 25, 123} { - require.NoError(t, idx.AddParticipantsToIndexes(chk, "test", accounts)) - } - - idx.Flush() // saves to disk - - // Try purging the index - err = purgeIndex(tempFile, historyarchive.Range{Low: 15 * freq, High: 22 * freq}) - require.NoError(t, err) - - // Check to make sure it worked. - idx, err = index.Connect(tempFile) - require.NoError(t, err) - - // Ensure that the index is in the expected state. - indices, err := idx.Read(accounts[0]) - require.NoError(t, err) - require.Contains(t, indices, "test") - - index := indices["test"] - i, err := index.NextActiveBit(0) - require.NoError(t, err) - require.EqualValues(t, 14, i) - - i, err = index.NextActiveBit(15) - require.NoError(t, err) - require.EqualValues(t, 25, i) - - i, err = index.NextActiveBit(i + 1) - require.NoError(t, err) - require.EqualValues(t, 123, i) -} diff --git a/gxdr/xdr_generated.go b/gxdr/xdr_generated.go index 7265cb5a71..0b41834ce9 100644 --- a/gxdr/xdr_generated.go +++ b/gxdr/xdr_generated.go @@ -1,4 +1,4 @@ -// Code generated by goxdr -p gxdr -enum-comments -o gxdr/xdr_generated.go xdr/Stellar-SCP.x xdr/Stellar-ledger-entries.x xdr/Stellar-ledger.x xdr/Stellar-overlay.x xdr/Stellar-transaction.x xdr/Stellar-types.x xdr/Stellar-contract-env-meta.x xdr/Stellar-contract-meta.x xdr/Stellar-contract-spec.x xdr/Stellar-contract.x xdr/Stellar-internal.x xdr/Stellar-contract-config-setting.x xdr/Stellar-lighthorizon.x xdr/Stellar-exporter.x; DO NOT EDIT. +// Code generated by goxdr -p gxdr -enum-comments -o gxdr/xdr_generated.go xdr/Stellar-SCP.x xdr/Stellar-ledger-entries.x xdr/Stellar-ledger.x xdr/Stellar-overlay.x xdr/Stellar-transaction.x xdr/Stellar-types.x xdr/Stellar-contract-env-meta.x xdr/Stellar-contract-meta.x xdr/Stellar-contract-spec.x xdr/Stellar-contract.x xdr/Stellar-internal.x xdr/Stellar-contract-config-setting.x xdr/Stellar-exporter.x; DO NOT EDIT. package gxdr @@ -4622,37 +4622,6 @@ type ConfigSettingEntry struct { _u interface{} } -type BitmapIndex struct { - FirstBit Uint32 - LastBit Uint32 - Bitmap Value -} - -type TrieIndex struct { - // goxdr gives an error if we simply use "version" as an identifier - Version_ Uint32 - Root TrieNode -} - -type TrieNodeChild struct { - Key [1]byte - Node TrieNode -} - -type TrieNode struct { - Prefix Value - Value Value - Children []TrieNodeChild -} - -type SerializedLedgerCloseMeta struct { - // The union discriminant V selects among the following arms: - // 0: - // V0() *LedgerCloseMeta - V int32 - _u interface{} -} - // Batch of ledgers along with their transaction metadata type LedgerCloseMetaBatch struct { // starting ledger sequence number in the batch @@ -30202,211 +30171,6 @@ func (u *ConfigSettingEntry) XdrRecurse(x XDR, name string) { } func XDR_ConfigSettingEntry(v *ConfigSettingEntry) *ConfigSettingEntry { return v } -type XdrType_BitmapIndex = *BitmapIndex - -func (v *BitmapIndex) XdrPointer() interface{} { return v } -func (BitmapIndex) XdrTypeName() string { return "BitmapIndex" } -func (v BitmapIndex) XdrValue() interface{} { return v } -func (v *BitmapIndex) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *BitmapIndex) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sfirstBit", name), XDR_Uint32(&v.FirstBit)) - x.Marshal(x.Sprintf("%slastBit", name), XDR_Uint32(&v.LastBit)) - x.Marshal(x.Sprintf("%sbitmap", name), XDR_Value(&v.Bitmap)) -} -func XDR_BitmapIndex(v *BitmapIndex) *BitmapIndex { return v } - -type XdrType_TrieIndex = *TrieIndex - -func (v *TrieIndex) XdrPointer() interface{} { return v } -func (TrieIndex) XdrTypeName() string { return "TrieIndex" } -func (v TrieIndex) XdrValue() interface{} { return v } -func (v *TrieIndex) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TrieIndex) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sversion_", name), XDR_Uint32(&v.Version_)) - x.Marshal(x.Sprintf("%sroot", name), XDR_TrieNode(&v.Root)) -} -func XDR_TrieIndex(v *TrieIndex) *TrieIndex { return v } - -type _XdrArray_1_opaque [1]byte - -func (v *_XdrArray_1_opaque) GetByteSlice() []byte { return v[:] } -func (v *_XdrArray_1_opaque) XdrTypeName() string { return "opaque[]" } -func (v *_XdrArray_1_opaque) XdrValue() interface{} { return v[:] } -func (v *_XdrArray_1_opaque) XdrPointer() interface{} { return (*[1]byte)(v) } -func (v *_XdrArray_1_opaque) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *_XdrArray_1_opaque) String() string { return fmt.Sprintf("%x", v[:]) } -func (v *_XdrArray_1_opaque) Scan(ss fmt.ScanState, c rune) error { - return XdrArrayOpaqueScan(v[:], ss, c) -} -func (_XdrArray_1_opaque) XdrArraySize() uint32 { - const bound uint32 = 1 // Force error if not const or doesn't fit - return bound -} - -type XdrType_TrieNodeChild = *TrieNodeChild - -func (v *TrieNodeChild) XdrPointer() interface{} { return v } -func (TrieNodeChild) XdrTypeName() string { return "TrieNodeChild" } -func (v TrieNodeChild) XdrValue() interface{} { return v } -func (v *TrieNodeChild) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TrieNodeChild) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%skey", name), (*_XdrArray_1_opaque)(&v.Key)) - x.Marshal(x.Sprintf("%snode", name), XDR_TrieNode(&v.Node)) -} -func XDR_TrieNodeChild(v *TrieNodeChild) *TrieNodeChild { return v } - -type _XdrVec_unbounded_TrieNodeChild []TrieNodeChild - -func (_XdrVec_unbounded_TrieNodeChild) XdrBound() uint32 { - const bound uint32 = 4294967295 // Force error if not const or doesn't fit - return bound -} -func (_XdrVec_unbounded_TrieNodeChild) XdrCheckLen(length uint32) { - if length > uint32(4294967295) { - XdrPanic("_XdrVec_unbounded_TrieNodeChild length %d exceeds bound 4294967295", length) - } else if int(length) < 0 { - XdrPanic("_XdrVec_unbounded_TrieNodeChild length %d exceeds max int", length) - } -} -func (v _XdrVec_unbounded_TrieNodeChild) GetVecLen() uint32 { return uint32(len(v)) } -func (v *_XdrVec_unbounded_TrieNodeChild) SetVecLen(length uint32) { - v.XdrCheckLen(length) - if int(length) <= cap(*v) { - if int(length) != len(*v) { - *v = (*v)[:int(length)] - } - return - } - newcap := 2 * cap(*v) - if newcap < int(length) { // also catches overflow where 2*cap < 0 - newcap = int(length) - } else if bound := uint(4294967295); uint(newcap) > bound { - if int(bound) < 0 { - bound = ^uint(0) >> 1 - } - newcap = int(bound) - } - nv := make([]TrieNodeChild, int(length), newcap) - copy(nv, *v) - *v = nv -} -func (v *_XdrVec_unbounded_TrieNodeChild) XdrMarshalN(x XDR, name string, n uint32) { - v.XdrCheckLen(n) - for i := 0; i < int(n); i++ { - if i >= len(*v) { - v.SetVecLen(uint32(i + 1)) - } - XDR_TrieNodeChild(&(*v)[i]).XdrMarshal(x, x.Sprintf("%s[%d]", name, i)) - } - if int(n) < len(*v) { - *v = (*v)[:int(n)] - } -} -func (v *_XdrVec_unbounded_TrieNodeChild) XdrRecurse(x XDR, name string) { - size := XdrSize{Size: uint32(len(*v)), Bound: 4294967295} - x.Marshal(name, &size) - v.XdrMarshalN(x, name, size.Size) -} -func (_XdrVec_unbounded_TrieNodeChild) XdrTypeName() string { return "TrieNodeChild<>" } -func (v *_XdrVec_unbounded_TrieNodeChild) XdrPointer() interface{} { return (*[]TrieNodeChild)(v) } -func (v _XdrVec_unbounded_TrieNodeChild) XdrValue() interface{} { return ([]TrieNodeChild)(v) } -func (v *_XdrVec_unbounded_TrieNodeChild) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } - -type XdrType_TrieNode = *TrieNode - -func (v *TrieNode) XdrPointer() interface{} { return v } -func (TrieNode) XdrTypeName() string { return "TrieNode" } -func (v TrieNode) XdrValue() interface{} { return v } -func (v *TrieNode) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (v *TrieNode) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - x.Marshal(x.Sprintf("%sprefix", name), XDR_Value(&v.Prefix)) - x.Marshal(x.Sprintf("%svalue", name), XDR_Value(&v.Value)) - x.Marshal(x.Sprintf("%schildren", name), (*_XdrVec_unbounded_TrieNodeChild)(&v.Children)) -} -func XDR_TrieNode(v *TrieNode) *TrieNode { return v } - -var _XdrTags_SerializedLedgerCloseMeta = map[int32]bool{ - XdrToI32(0): true, -} - -func (_ SerializedLedgerCloseMeta) XdrValidTags() map[int32]bool { - return _XdrTags_SerializedLedgerCloseMeta -} -func (u *SerializedLedgerCloseMeta) V0() *LedgerCloseMeta { - switch u.V { - case 0: - if v, ok := u._u.(*LedgerCloseMeta); ok { - return v - } else { - var zero LedgerCloseMeta - u._u = &zero - return &zero - } - default: - XdrPanic("SerializedLedgerCloseMeta.V0 accessed when V == %v", u.V) - return nil - } -} -func (u SerializedLedgerCloseMeta) XdrValid() bool { - switch u.V { - case 0: - return true - } - return false -} -func (u *SerializedLedgerCloseMeta) XdrUnionTag() XdrNum32 { - return XDR_int32(&u.V) -} -func (u *SerializedLedgerCloseMeta) XdrUnionTagName() string { - return "V" -} -func (u *SerializedLedgerCloseMeta) XdrUnionBody() XdrType { - switch u.V { - case 0: - return XDR_LedgerCloseMeta(u.V0()) - } - return nil -} -func (u *SerializedLedgerCloseMeta) XdrUnionBodyName() string { - switch u.V { - case 0: - return "V0" - } - return "" -} - -type XdrType_SerializedLedgerCloseMeta = *SerializedLedgerCloseMeta - -func (v *SerializedLedgerCloseMeta) XdrPointer() interface{} { return v } -func (SerializedLedgerCloseMeta) XdrTypeName() string { return "SerializedLedgerCloseMeta" } -func (v SerializedLedgerCloseMeta) XdrValue() interface{} { return v } -func (v *SerializedLedgerCloseMeta) XdrMarshal(x XDR, name string) { x.Marshal(name, v) } -func (u *SerializedLedgerCloseMeta) XdrRecurse(x XDR, name string) { - if name != "" { - name = x.Sprintf("%s.", name) - } - XDR_int32(&u.V).XdrMarshal(x, x.Sprintf("%sv", name)) - switch u.V { - case 0: - x.Marshal(x.Sprintf("%sv0", name), XDR_LedgerCloseMeta(u.V0())) - return - } - XdrPanic("invalid V (%v) in SerializedLedgerCloseMeta", u.V) -} -func XDR_SerializedLedgerCloseMeta(v *SerializedLedgerCloseMeta) *SerializedLedgerCloseMeta { return v } - type _XdrVec_unbounded_LedgerCloseMeta []LedgerCloseMeta func (_XdrVec_unbounded_LedgerCloseMeta) XdrBound() uint32 { diff --git a/ingest/ledgerbackend/history_archive_backend.go b/ingest/ledgerbackend/history_archive_backend.go deleted file mode 100644 index 331f43032d..0000000000 --- a/ingest/ledgerbackend/history_archive_backend.go +++ /dev/null @@ -1,51 +0,0 @@ -package ledgerbackend - -import ( - "context" - "fmt" - - "github.com/stellar/go/metaarchive" - "github.com/stellar/go/xdr" -) - -type HistoryArchiveBackend struct { - metaArchive metaarchive.MetaArchive -} - -func NewHistoryArchiveBackend(metaArchive metaarchive.MetaArchive) *HistoryArchiveBackend { - return &HistoryArchiveBackend{ - metaArchive: metaArchive, - } -} - -func (b *HistoryArchiveBackend) GetLatestLedgerSequence(ctx context.Context) (uint32, error) { - return b.metaArchive.GetLatestLedgerSequence(ctx) -} - -func (b *HistoryArchiveBackend) PrepareRange(ctx context.Context, ledgerRange Range) error { - // Noop - return nil -} - -func (b *HistoryArchiveBackend) IsPrepared(ctx context.Context, ledgerRange Range) (bool, error) { - // Noop - return true, nil -} - -func (b *HistoryArchiveBackend) GetLedger(ctx context.Context, sequence uint32) (xdr.LedgerCloseMeta, error) { - serializedLedger, err := b.metaArchive.GetLedger(ctx, sequence) - if err != nil { - return xdr.LedgerCloseMeta{}, err - } - - output, isV0 := serializedLedger.GetV0() - if !isV0 { - return xdr.LedgerCloseMeta{}, fmt.Errorf("unexpected serialized ledger version number (0x%x)", serializedLedger.V) - } - return output, nil -} - -func (b *HistoryArchiveBackend) Close() error { - // Noop - return nil -} diff --git a/metaarchive/main.go b/metaarchive/main.go deleted file mode 100644 index 7d06a46f9a..0000000000 --- a/metaarchive/main.go +++ /dev/null @@ -1,62 +0,0 @@ -package metaarchive - -import ( - "bytes" - "context" - "io" - "os" - "strconv" - - "github.com/stellar/go/support/errors" - "github.com/stellar/go/support/storage" - "github.com/stellar/go/xdr" -) - -type MetaArchive interface { - GetLatestLedgerSequence(ctx context.Context) (uint32, error) - GetLedger(ctx context.Context, sequence uint32) (xdr.SerializedLedgerCloseMeta, error) -} - -type metaArchive struct { - s storage.Storage -} - -func NewMetaArchive(b storage.Storage) MetaArchive { - return &metaArchive{s: b} -} - -func (m *metaArchive) GetLatestLedgerSequence(ctx context.Context) (uint32, error) { - r, err := m.s.GetFile("latest") - if os.IsNotExist(err) { - return 2, nil - } else if err != nil { - return 0, errors.Wrap(err, "could not open latest ledger bucket") - } - defer r.Close() - var buf bytes.Buffer - if _, err = io.Copy(&buf, r); err != nil { - return 0, errors.Wrap(err, "could not read latest ledger") - } - parsed, err := strconv.ParseUint(buf.String(), 10, 32) - if err != nil { - return 0, errors.Wrapf(err, "could not parse latest ledger: %q", buf.String()) - } - return uint32(parsed), nil -} - -func (m *metaArchive) GetLedger(ctx context.Context, sequence uint32) (xdr.SerializedLedgerCloseMeta, error) { - var ledger xdr.SerializedLedgerCloseMeta - r, err := m.s.GetFile("ledgers/" + strconv.FormatUint(uint64(sequence), 10)) - if err != nil { - return xdr.SerializedLedgerCloseMeta{}, err - } - defer r.Close() - var buf bytes.Buffer - if _, err = io.Copy(&buf, r); err != nil { - return xdr.SerializedLedgerCloseMeta{}, err - } - if err = ledger.UnmarshalBinary(buf.Bytes()); err != nil { - return xdr.SerializedLedgerCloseMeta{}, err - } - return ledger, nil -} diff --git a/xdr/xdr_generated.go b/xdr/xdr_generated.go index c47ab760c9..fb7fb7471e 100644 --- a/xdr/xdr_generated.go +++ b/xdr/xdr_generated.go @@ -13,7 +13,6 @@ // xdr/Stellar-internal.x // xdr/Stellar-ledger-entries.x // xdr/Stellar-ledger.x -// xdr/Stellar-lighthorizon.x // xdr/Stellar-overlay.x // xdr/Stellar-transaction.x // xdr/Stellar-types.x @@ -43,7 +42,6 @@ var XdrFilesSHA256 = map[string]string{ "xdr/Stellar-internal.x": "227835866c1b2122d1eaf28839ba85ea7289d1cb681dda4ca619c2da3d71fe00", "xdr/Stellar-ledger-entries.x": "77dc7062ae6d0812136333e12e35b2294d7c2896a536be9c811eb0ed2abbbccb", "xdr/Stellar-ledger.x": "46c1c55972750b97650ff00788a2be4764975b787ef51c8fa931c56e2028a3c4", - "xdr/Stellar-lighthorizon.x": "1aac09eaeda224154f653a0c95f02167be0c110fc295bb41b756a080eb8c06df", "xdr/Stellar-overlay.x": "8c73b7c3ad974e7fc4aa4fdf34f7ad50053406254efbd7406c96657cf41691d3", "xdr/Stellar-transaction.x": "0d2b35a331a540b48643925d0869857236eb2487c02d340ea32e365e784ea2b8", "xdr/Stellar-types.x": "6e3b13f0d3e360b09fa5e2b0e55d43f4d974a769df66afb34e8aecbb329d3f15", @@ -58962,482 +58960,6 @@ func (s ConfigSettingEntry) xdrType() {} var _ xdrType = (*ConfigSettingEntry)(nil) -// BitmapIndex is an XDR Struct defines as: -// -// struct BitmapIndex { -// uint32 firstBit; -// uint32 lastBit; -// Value bitmap; -// }; -type BitmapIndex struct { - FirstBit Uint32 - LastBit Uint32 - Bitmap Value -} - -// EncodeTo encodes this value using the Encoder. -func (s *BitmapIndex) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.FirstBit.EncodeTo(e); err != nil { - return err - } - if err = s.LastBit.EncodeTo(e); err != nil { - return err - } - if err = s.Bitmap.EncodeTo(e); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*BitmapIndex)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *BitmapIndex) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { - if maxDepth == 0 { - return 0, fmt.Errorf("decoding BitmapIndex: %w", ErrMaxDecodingDepthReached) - } - maxDepth -= 1 - var err error - var n, nTmp int - nTmp, err = s.FirstBit.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %w", err) - } - nTmp, err = s.LastBit.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %w", err) - } - nTmp, err = s.Bitmap.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Value: %w", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s BitmapIndex) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *BitmapIndex) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - o := xdr.DefaultDecodeOptions - o.MaxInputLen = len(inp) - d := xdr.NewDecoderWithOptions(r, o) - _, err := s.DecodeFrom(d, o.MaxDepth) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*BitmapIndex)(nil) - _ encoding.BinaryUnmarshaler = (*BitmapIndex)(nil) -) - -// xdrType signals that this type represents XDR values defined by this package. -func (s BitmapIndex) xdrType() {} - -var _ xdrType = (*BitmapIndex)(nil) - -// TrieIndex is an XDR Struct defines as: -// -// struct TrieIndex { -// uint32 version_; // goxdr gives an error if we simply use "version" as an identifier -// TrieNode root; -// }; -type TrieIndex struct { - Version Uint32 - Root TrieNode -} - -// EncodeTo encodes this value using the Encoder. -func (s *TrieIndex) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Version.EncodeTo(e); err != nil { - return err - } - if err = s.Root.EncodeTo(e); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*TrieIndex)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *TrieIndex) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { - if maxDepth == 0 { - return 0, fmt.Errorf("decoding TrieIndex: %w", ErrMaxDecodingDepthReached) - } - maxDepth -= 1 - var err error - var n, nTmp int - nTmp, err = s.Version.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Uint32: %w", err) - } - nTmp, err = s.Root.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TrieNode: %w", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TrieIndex) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TrieIndex) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - o := xdr.DefaultDecodeOptions - o.MaxInputLen = len(inp) - d := xdr.NewDecoderWithOptions(r, o) - _, err := s.DecodeFrom(d, o.MaxDepth) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*TrieIndex)(nil) - _ encoding.BinaryUnmarshaler = (*TrieIndex)(nil) -) - -// xdrType signals that this type represents XDR values defined by this package. -func (s TrieIndex) xdrType() {} - -var _ xdrType = (*TrieIndex)(nil) - -// TrieNodeChild is an XDR Struct defines as: -// -// struct TrieNodeChild { -// opaque key[1]; -// TrieNode node; -// }; -type TrieNodeChild struct { - Key [1]byte `xdrmaxsize:"1"` - Node TrieNode -} - -// EncodeTo encodes this value using the Encoder. -func (s *TrieNodeChild) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeFixedOpaque(s.Key[:]); err != nil { - return err - } - if err = s.Node.EncodeTo(e); err != nil { - return err - } - return nil -} - -var _ decoderFrom = (*TrieNodeChild)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *TrieNodeChild) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { - if maxDepth == 0 { - return 0, fmt.Errorf("decoding TrieNodeChild: %w", ErrMaxDecodingDepthReached) - } - maxDepth -= 1 - var err error - var n, nTmp int - nTmp, err = d.DecodeFixedOpaqueInplace(s.Key[:]) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Key: %w", err) - } - nTmp, err = s.Node.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TrieNode: %w", err) - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TrieNodeChild) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TrieNodeChild) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - o := xdr.DefaultDecodeOptions - o.MaxInputLen = len(inp) - d := xdr.NewDecoderWithOptions(r, o) - _, err := s.DecodeFrom(d, o.MaxDepth) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*TrieNodeChild)(nil) - _ encoding.BinaryUnmarshaler = (*TrieNodeChild)(nil) -) - -// xdrType signals that this type represents XDR values defined by this package. -func (s TrieNodeChild) xdrType() {} - -var _ xdrType = (*TrieNodeChild)(nil) - -// TrieNode is an XDR Struct defines as: -// -// struct TrieNode { -// Value prefix; -// Value value; -// TrieNodeChild children<>; -// }; -type TrieNode struct { - Prefix Value - Value Value - Children []TrieNodeChild -} - -// EncodeTo encodes this value using the Encoder. -func (s *TrieNode) EncodeTo(e *xdr.Encoder) error { - var err error - if err = s.Prefix.EncodeTo(e); err != nil { - return err - } - if err = s.Value.EncodeTo(e); err != nil { - return err - } - if _, err = e.EncodeUint(uint32(len(s.Children))); err != nil { - return err - } - for i := 0; i < len(s.Children); i++ { - if err = s.Children[i].EncodeTo(e); err != nil { - return err - } - } - return nil -} - -var _ decoderFrom = (*TrieNode)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (s *TrieNode) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { - if maxDepth == 0 { - return 0, fmt.Errorf("decoding TrieNode: %w", ErrMaxDecodingDepthReached) - } - maxDepth -= 1 - var err error - var n, nTmp int - nTmp, err = s.Prefix.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Value: %w", err) - } - nTmp, err = s.Value.DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Value: %w", err) - } - var l uint32 - l, nTmp, err = d.DecodeUint() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TrieNodeChild: %w", err) - } - s.Children = nil - if l > 0 { - if il, ok := d.InputLen(); ok && uint(il) < uint(l) { - return n, fmt.Errorf("decoding TrieNodeChild: length (%d) exceeds remaining input length (%d)", l, il) - } - s.Children = make([]TrieNodeChild, l) - for i := uint32(0); i < l; i++ { - nTmp, err = s.Children[i].DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding TrieNodeChild: %w", err) - } - } - } - return n, nil -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s TrieNode) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *TrieNode) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - o := xdr.DefaultDecodeOptions - o.MaxInputLen = len(inp) - d := xdr.NewDecoderWithOptions(r, o) - _, err := s.DecodeFrom(d, o.MaxDepth) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*TrieNode)(nil) - _ encoding.BinaryUnmarshaler = (*TrieNode)(nil) -) - -// xdrType signals that this type represents XDR values defined by this package. -func (s TrieNode) xdrType() {} - -var _ xdrType = (*TrieNode)(nil) - -// SerializedLedgerCloseMeta is an XDR Union defines as: -// -// union SerializedLedgerCloseMeta switch (int v) -// { -// case 0: -// LedgerCloseMeta v0; -// }; -type SerializedLedgerCloseMeta struct { - V int32 - V0 *LedgerCloseMeta -} - -// SwitchFieldName returns the field name in which this union's -// discriminant is stored -func (u SerializedLedgerCloseMeta) SwitchFieldName() string { - return "V" -} - -// ArmForSwitch returns which field name should be used for storing -// the value for an instance of SerializedLedgerCloseMeta -func (u SerializedLedgerCloseMeta) ArmForSwitch(sw int32) (string, bool) { - switch int32(sw) { - case 0: - return "V0", true - } - return "-", false -} - -// NewSerializedLedgerCloseMeta creates a new SerializedLedgerCloseMeta. -func NewSerializedLedgerCloseMeta(v int32, value interface{}) (result SerializedLedgerCloseMeta, err error) { - result.V = v - switch int32(v) { - case 0: - tv, ok := value.(LedgerCloseMeta) - if !ok { - err = errors.New("invalid value, must be LedgerCloseMeta") - return - } - result.V0 = &tv - } - return -} - -// MustV0 retrieves the V0 value from the union, -// panicing if the value is not set. -func (u SerializedLedgerCloseMeta) MustV0() LedgerCloseMeta { - val, ok := u.GetV0() - - if !ok { - panic("arm V0 is not set") - } - - return val -} - -// GetV0 retrieves the V0 value from the union, -// returning ok if the union's switch indicated the value is valid. -func (u SerializedLedgerCloseMeta) GetV0() (result LedgerCloseMeta, ok bool) { - armName, _ := u.ArmForSwitch(int32(u.V)) - - if armName == "V0" { - result = *u.V0 - ok = true - } - - return -} - -// EncodeTo encodes this value using the Encoder. -func (u SerializedLedgerCloseMeta) EncodeTo(e *xdr.Encoder) error { - var err error - if _, err = e.EncodeInt(int32(u.V)); err != nil { - return err - } - switch int32(u.V) { - case 0: - if err = (*u.V0).EncodeTo(e); err != nil { - return err - } - return nil - } - return fmt.Errorf("V (int32) switch value '%d' is not valid for union SerializedLedgerCloseMeta", u.V) -} - -var _ decoderFrom = (*SerializedLedgerCloseMeta)(nil) - -// DecodeFrom decodes this value using the Decoder. -func (u *SerializedLedgerCloseMeta) DecodeFrom(d *xdr.Decoder, maxDepth uint) (int, error) { - if maxDepth == 0 { - return 0, fmt.Errorf("decoding SerializedLedgerCloseMeta: %w", ErrMaxDecodingDepthReached) - } - maxDepth -= 1 - var err error - var n, nTmp int - u.V, nTmp, err = d.DecodeInt() - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding Int: %w", err) - } - switch int32(u.V) { - case 0: - u.V0 = new(LedgerCloseMeta) - nTmp, err = (*u.V0).DecodeFrom(d, maxDepth) - n += nTmp - if err != nil { - return n, fmt.Errorf("decoding LedgerCloseMeta: %w", err) - } - return n, nil - } - return n, fmt.Errorf("union SerializedLedgerCloseMeta has invalid V (int32) switch value '%d'", u.V) -} - -// MarshalBinary implements encoding.BinaryMarshaler. -func (s SerializedLedgerCloseMeta) MarshalBinary() ([]byte, error) { - b := bytes.Buffer{} - e := xdr.NewEncoder(&b) - err := s.EncodeTo(e) - return b.Bytes(), err -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler. -func (s *SerializedLedgerCloseMeta) UnmarshalBinary(inp []byte) error { - r := bytes.NewReader(inp) - o := xdr.DefaultDecodeOptions - o.MaxInputLen = len(inp) - d := xdr.NewDecoderWithOptions(r, o) - _, err := s.DecodeFrom(d, o.MaxDepth) - return err -} - -var ( - _ encoding.BinaryMarshaler = (*SerializedLedgerCloseMeta)(nil) - _ encoding.BinaryUnmarshaler = (*SerializedLedgerCloseMeta)(nil) -) - -// xdrType signals that this type represents XDR values defined by this package. -func (s SerializedLedgerCloseMeta) xdrType() {} - -var _ xdrType = (*SerializedLedgerCloseMeta)(nil) - // LedgerCloseMetaBatch is an XDR Struct defines as: // // struct LedgerCloseMetaBatch