Add benchmark script

This commit is contained in:
Artur
2025-05-21 16:25:43 -03:00
parent 09cc13b3fc
commit dfe07b95dc
7 changed files with 347 additions and 2 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
/target
__pycache__
.venv

58
benchmark/benchmark.py Normal file
View File

@@ -0,0 +1,58 @@
import json
import random
from locust import HttpUser, task, between
class TransactionAPIUser(HttpUser):
"""
A Locust user class that simulates users hitting a transaction API
with transaction hashes loaded from a JSON file.
"""
# Simulate user waiting time between requests (in seconds)
# This will be a random float between 1 and 2 seconds.
wait_time = between(1, 2)
# Base URL for the API endpoint
# IMPORTANT: Ensure your local API is running on this address and port.
host = "http://localhost:8081"
def on_start(self):
"""
This method is called when a Locust user starts.
It loads the transaction hashes from the 'tx_hashes.json' file.
"""
self.tx_hashes = []
try:
with open('tx_hashes.json', 'r') as f:
self.tx_hashes = json.load(f)
print(f"Loaded {len(self.tx_hashes)} transaction hashes from tx_hashes.json")
if not self.tx_hashes:
print("Warning: tx_hashes.json is empty. No transactions to test.")
except FileNotFoundError:
print("Error: tx_hashes.json not found. Please run the Monero Transaction Hash Collector script first.")
# Exit or handle gracefully if the file is essential
self.environment.runner.quit() # This will stop the Locust test if the file is missing
except json.JSONDecodeError:
print("Error: Could not decode JSON from tx_hashes.json. Ensure it's a valid JSON array.")
self.environment.runner.quit() # This will stop the Locust test
@task
def get_transaction_by_hash(self):
"""
This task simulates a user requesting a transaction by its hash.
It picks a random hash from the loaded list and makes a GET request.
"""
if not self.tx_hashes:
print("No transaction hashes available to test.")
return
# Choose a random transaction hash from the loaded list
random_tx_hash = random.choice(self.tx_hashes)
# Define the API endpoint path with the chosen hash
endpoint = f"/api/transaction/{random_tx_hash}"
# Make the GET request
# The 'name' parameter groups requests in Locust's statistics.
# Using a parameterized name like "/api/transaction/[hash]" is good practice
# to avoid creating a unique entry for every single hash in the statistics.
self.client.get(endpoint, name="/api/transaction/[tx_hash]")

View File

@@ -0,0 +1 @@
locust

View File

@@ -0,0 +1,80 @@
import requests
import json
import time
def collect_tx_hashes(start_block: int = 3000000, target_count: int = 100, output_filename: str = "tx_hashes.json"):
"""
Collects transaction hashes from the xmr.se API, starting from a given block number,
until a target number of unique transaction hashes are collected.
The collected hashes are then stored in a JSON file.
Args:
start_block (int): The starting block number to fetch data from.
target_count (int): The desired number of transaction hashes to collect.
output_filename (str): The name of the JSON file to store the hashes.
"""
base_url = "https://xmr.se/api/block/"
current_block_number = start_block
tx_hashes = []
collected_count = 0
print(f"Starting to collect {target_count} transaction hashes from block {start_block}...")
while collected_count < target_count:
url = f"{base_url}{current_block_number}"
print(f"Fetching data from: {url}")
try:
response = requests.get(url, timeout=10) # Set a timeout for the request
response.raise_for_status() # Raise an HTTPError for bad responses (4xx or 5xx)
data = response.json()
# Navigate to the transaction list within the response
# The structure is response.data.txs[]
if 'data' in data and 'txs' in data['data'] and isinstance(data['data']['txs'], list):
transactions = data['data']['txs']
for tx in transactions:
if not tx['coinbase']:
tx_hashes.append(tx['tx_hash'])
collected_count += 1
if collected_count >= target_count:
break # Exit inner loop if target count is reached
print(f"Collected {collected_count}/{target_count} transaction hashes.")
else:
print(f"Warning: 'data' or 'txs' key not found or 'txs' is not a list in response for block {current_block_number}.")
except requests.exceptions.HTTPError as http_err:
print(f"HTTP error occurred for block {current_block_number}: {http_err}")
if response.status_code == 404:
print(f"Block {current_block_number} not found. Skipping to next block.")
# Consider adding a break or more robust error handling if 404s are frequent
except requests.exceptions.ConnectionError as conn_err:
print(f"Connection error occurred: {conn_err}. Retrying in 5 seconds...")
time.sleep(5) # Wait before retrying on connection error
continue # Skip incrementing block number and retry current block
except requests.exceptions.Timeout as timeout_err:
print(f"Request timed out: {timeout_err}. Retrying in 5 seconds...")
time.sleep(5) # Wait before retrying on timeout
continue # Skip incrementing block number and retry current block
except json.JSONDecodeError as json_err:
print(f"JSON decode error for block {current_block_number}: {json_err}. Response content: {response.text[:200]}...")
except Exception as err:
print(f"An unexpected error occurred for block {current_block_number}: {err}")
current_block_number += 1
time.sleep(0.1) # Small delay to avoid overwhelming the API
# Ensure we only store the exact target_count if more were collected in the last iteration
final_tx_hashes = tx_hashes[:target_count]
try:
with open(output_filename, 'w') as f:
json.dump(final_tx_hashes, f, indent=4)
print(f"\nSuccessfully collected {len(final_tx_hashes)} transaction hashes and saved to '{output_filename}'")
except IOError as io_err:
print(f"Error writing to file '{output_filename}': {io_err}")
if __name__ == "__main__":
# You can modify the starting block and target count here
collect_tx_hashes(start_block=3000000, target_count=100)

102
benchmark/tx_hashes.json Normal file
View File

@@ -0,0 +1,102 @@
[
"e4516854a5984eaf5f8750ac7af41d1e0b2c602a2297a673001e8c0af88eba11",
"fc4f31a3c568e1584b7ceb2cb1b2ffb02c1a8a968f78d5a032baf82ff90187d0",
"a0eed140d54e78336c4b04952fad9cbf4dd00504fc56178446ebb994f2e90d62",
"f3f4c1b5fc8bc98957d6d890f4e245ce72f78d505ba1d96dcd5e23c295e8cac3",
"094fd49f5ec60f2b1f657123317785bc62eac5b7ee3518fe59d7ac1188054cf7",
"1ef22128e63987b203d0869c5ce313ab9c441531497e3b163c8942fae243737d",
"5417f9278d5c73e292e22df71e3fcf7eb09a21898b7b46e1aa2289572cf5e7ae",
"d9ebf7466bb0f8276940eab0e34730a12f71f6e44947b06337488e67fa1d12ab",
"9db512c1b97fe028be832423661c0d2755f3c6899ad0f8dbd9a1025dd75d6abd",
"e9702eff90d08d03d0f8cbcfecacf31df0b70ba4b293aea233eb14372cff9b8a",
"dd94e646fa8d98a4007206bac2ddf7f2a4746a4094eaa5be30f162509cf858e7",
"a5b8788446bccb3df59751f6e1da0048acd0f7a7d4e7f3dc6e88f0f10498b0c5",
"631847b11cf027a066c445c08dfd35d9884ebf7ce0d1830061338706b9cda954",
"f84e65d3a6c4f1f06e6e24a87f122566523e395345fd57a8eb3e071dfabc91b9",
"79b489f1426580d0a9b26b52f88b443fa0d474070e455f22c033cadd2d1594a0",
"f5602a78e8f81af85eb36a4b2eacd88d21ef4994e3c8a2982ffa60a9303212a2",
"1e1584cb8f03af5ba61dfaa0b71ce40be519f74fdde908845eba0726452e2da0",
"a67169a6d6d4df8871368b68bfbf875a43a80e6b70f0196e02bed02097eb71aa",
"6a0819a62f928f761d67e539147ddc272288cb51730b6240c8265584f15c84eb",
"c725f0601869da8a51f19be1dcdcf879d7de57ba739943bbbecb6b0510bd4867",
"c2bf18cdd28082a766dceb4ec9925efd20cde34b0465918e94cc7c7b8062a454",
"a7c68dc7abfd5fa6855dd8f9a47e204af4711d0176aec7cb612402c577e47aee",
"1f632de75213303c1e2e2bd7fcd22de6a1b6e23899381364b15a7742c996d7f3",
"e2bc2f2258c08bb1b852e9ddebd108dc8744f07ffbf3030d052ab6d0202996be",
"a037ae64dc54257a68e1bfc466b6355d8fab3caecc6057aa1ea1c20fb04c12ab",
"17c3f6cac2ffed6e824619ca6aa5f439a64ab9a66512669e9c04b19dabaad4c1",
"2e200d856efc21625712480f47e33c306703afbb7dbc4a862ebd7bf65403a0b9",
"3539854d443a4d1a3784dca49b6e57d2d396fc1a28419f06b969b358d1e4f2f7",
"a9f2a9d99bf2841d4087ab7c4cccb5e4f6feb53ba0ffe10f0e9498d2438f1d89",
"9149feb5f584c2ee053596a6ee39189823eb4e34955a68f780c36a8765407aab",
"92b7c827c9c85e730388129cf61321af73c679549e2c6df95c45db7c5733b4fb",
"069b9933c262747199a3c8381634ebc757e899f211b8ba6bd1470dac50ef47fe",
"2919431ca85b132c82e402e2478c6522173bedf3de8927bca1e01865fc32ba5e",
"636104a3cb6387efc749a23210fcc0e156114f54c9935d4796adaa4c01a42f53",
"adeaaf56b8567f5a78132af62cbd4665ac4c0d34ed93a9cef7f7cf484e5645e5",
"5234d3056dd30ad9204ff4f69ba7b1b1aaa277eb0a059d97adf6b070b2cc52d3",
"c36cd1ced56c62850f54da082e90b612b32c676196a99dd4ca2688afb656c162",
"fa5a45175d1c42192285d0399ef5b2bd70950ccf90a811c2a41b82799be5fce3",
"328eab94c55de4718c2a1c458161b8bec1a7e53f459fe9170ac4a47b35c3a796",
"b5e38373974647da48c5d937ec22c9b33c5a4039f1ae59dae025b9d2eeb15b5f",
"db5d1146a3cbc9134609181f84284e4b06b3c7cb1166624abef56afe096c23d8",
"e97738242692417a95c47832060dc045740c2cc472cb19002c4b6fbc2868a3b7",
"4048523ea0babed7f90458a72c0f1a175a263175666aa85c8fc080ae766b2209",
"318f90938ff73cd01f6c1098c934d25f8b0c2a2d2aac196e598ce6a977b26fdf",
"38631cb453c3785480741f39969a2eb92a55e0c82578d607f790208b02c54b0f",
"e114b12ce35f7b015ca176c9d273b7359da126d3ae140b189611727d6da7fab8",
"470a16e8f8468778c9d384de0f88d2d2f80f8490494208c7f59d2f01f998bae1",
"e8e53c8e10f16e2400ebcccd0e44b2b84fb9d535572eaf766e9bd18f504c13eb",
"44986f459e351541b5eb297a8de945b6d8e8dbece8af46a57745de32fd207b42",
"52b3937c2e93046f407df83c69e1fa9d44cc9823960bbf2e05b5ce13bc67d27e",
"2d0367eb966d4f0da6a3842054ae534e451883224deeab67447609d54a520418",
"bc57744670aed015fc21eb450b768b12f6c56a4e1c2986fe2ffe22462926234b",
"a9cdeb9bebc3d83ed004d9f5846279b96bf46ca7d706a986b3dd03556e04ab16",
"72f2e96f881ba6765f79e658b369e3965d3e2abaa70039c236109da1b16871d8",
"bfa8c9b5f817e4662ceb6c75c6d2bd5cd3a5581336f3c43de72ea639fbf89630",
"36c76018791abbfbedab60737c5035621e8744b68ca788df878db9f6f94928ad",
"19316f657a76272f711e6b86981ff1479ef645acca36cac7bf2cbbe0e44c5841",
"eb1904fe6bd0ca4e9a5b02ccffcfe59586a76d2b2cce885bade2c2cbc4ec14b4",
"a51e618dd7d40c490c75573d0090133e619168178beec893488769f47d00c21d",
"fca09eabc9cfbfafc5c7189a94e5de4ac513374631a60ccc45d3290e3ebc81a7",
"3097d916565e77353ad25194817a487ea5b6eee381683d879f8aeafeed294e41",
"5081ed79bec72c90dba7228ac3559e75a469741deb885777bfa813d341387779",
"2a12ac0b11cb44f822dab53abd3951006237b10e1751386689fc492706686b92",
"ee2a88bd0877bd510d95351ec8884b904c03f88cc1cb1eb5c3d6d9b68a309e65",
"e1d8622ddb8b6493d479ceab011ebea4461d31f50974c76575762cf19c0be7a4",
"870dcac7a63a16b87245f2c101302e43ebce0623ca378071caaa8ca37b9d9f8b",
"0feca0bcefc165cc1e80ad48a42044141b802a2036b076a428267468832974c7",
"201d58dfa1fa65e15597d2455889bf948af9b9fb513a29b35b76a8c2edaec83b",
"3e2f02dc1c5476e7424b1cba42846fc0fc5150143c2a6aa158d2727c811b2b94",
"fc2bcafdc800f1c0098a7d36b19e38a2b8999571747d8ab83ec2b004c1d31f92",
"75b1378f2259e82c4da7fc9ac3312be6f9f95959c14f45422ffab4f282d44976",
"41aa32ebd467af200e41380033f52b479cff31b3c6a49244e7f538445a15b7e7",
"d197a080476b16cde02e2094b3218d559ff7607eefd56f0039f3f1289377316c",
"6fe569037c25b45020e11dd40b68fcfdca92d43f741eff154682f6bc97ac00e3",
"342fbf352b1315a07bb323e6e313351193a11cd82eb5c4f1c3959186d8346d77",
"7bff0dbac2b48138bd252aed1adc4257b9acaafc78bbefa4028c8b9cfe29721f",
"6800a45ef775d6e16f71cdba440046e8c3cf89e6102edd72ea365fcd3feb748d",
"338a0c04f05a4cb72ae2fd6c9f63a09a23f8058b6784be7fe89989920ea04fd1",
"d2497bbe1487fede1026ec23291efb71d90651388f72907d7ad3e7b54a98596f",
"6106a66645cb7b8ea29bc158b54364e3ea047c4e2f1eaf059b537df1b5f3e3cc",
"29c6e7ce22da78f1e70a0c44d03ee1c93a3f8a50866d95b6d2a38c75dc3f550a",
"6f5c58b7b58aa767ef5eced1a9e8b50c893571bccee09ae4c2a8ad3acdb7eec5",
"58cd143bb4d6b69d95f274e931a3c388ecfe70c08e414f4f072cade3a36b1181",
"b1b478a3e95c3db616e060f3b163b96b83d7d3fd7205b7b4c4a4c864546f3b47",
"b59a030332f38a14ddbdc20fcad4b34680a4d69818a2daea92a7caac102750cf",
"724230dc6619ddc164da1fc2034dd004fa9a4485e6dac01262c0f50ad4b4024e",
"3cfda0d9fc76d76d607221e94062af9db3597d9847993b30163c0e0263ccf0f2",
"2d5c5ec9c8257bd4aabd023158b4100c39b9904b789a54dd33239e2a31186cc1",
"0dcd3646343b2feee40cdee761162787da7636659b6ef9ce2097982beaee8c15",
"f572b035bd92f8057d6108a016285c71ac6b801846020864815c9bfe3f048b55",
"7e017fb95bf2044e3dd5984c91d077eac0054bdbdc31f7a8809fb2d2fc49a437",
"ba3a05933d16c785e4e5db840ed82e16c7ada414f5640da58cae1f8f75dbbe22",
"bfe64afb2af6c9a19588d77dc773b9614eb2dbde9abd37ccf53ab69e4f10de41",
"939d1cbe8ba291a60835e017da354e166af6347e33710b2509d586254aec0864",
"3233f9c50820f9be8193696d63aae5cef956bd3eda56276e0530c45ec798bd9f",
"3a0cc247a8eeef427c989c67581288be84b6982213235f032228f3eb49e8e876",
"e497bcd51da87c5e6abfe8f357fdfdc767032d326934ee382a2a0db5d72a577e",
"19bee468445a280956ba35226d5b276f28c52fc3516ffdb6e64e58bdd826eba1",
"71745458610170b779880f57eef9399107398c88ad8bb85e6ee90f95972147f2",
"20e629aafea7078fdd1988f4a0c8fd61a0fab333bcbb55e808b40060987412c9"
]

View File

@@ -39,7 +39,7 @@ struct TransactionResponse {
pub extra: String,
}
#[get("/api/tx/{tx_hash}")]
#[get("/api/transaction/{tx_hash}")]
async fn get_tx(
env: web::Data<ConcreteEnv>,
tx_hash: web::Path<String>
@@ -266,7 +266,7 @@ async fn main() -> std::io::Result<()> {
.service(get_tx)
.service(get_block)
})
.bind(("127.0.0.1", 8080))?
.bind(("127.0.0.1", 8081))?
.run()
.await
}

102
tx_hashes.json Normal file
View File

@@ -0,0 +1,102 @@
[
"e4516854a5984eaf5f8750ac7af41d1e0b2c602a2297a673001e8c0af88eba11",
"fc4f31a3c568e1584b7ceb2cb1b2ffb02c1a8a968f78d5a032baf82ff90187d0",
"a0eed140d54e78336c4b04952fad9cbf4dd00504fc56178446ebb994f2e90d62",
"f3f4c1b5fc8bc98957d6d890f4e245ce72f78d505ba1d96dcd5e23c295e8cac3",
"094fd49f5ec60f2b1f657123317785bc62eac5b7ee3518fe59d7ac1188054cf7",
"1ef22128e63987b203d0869c5ce313ab9c441531497e3b163c8942fae243737d",
"5417f9278d5c73e292e22df71e3fcf7eb09a21898b7b46e1aa2289572cf5e7ae",
"d9ebf7466bb0f8276940eab0e34730a12f71f6e44947b06337488e67fa1d12ab",
"9db512c1b97fe028be832423661c0d2755f3c6899ad0f8dbd9a1025dd75d6abd",
"e9702eff90d08d03d0f8cbcfecacf31df0b70ba4b293aea233eb14372cff9b8a",
"dd94e646fa8d98a4007206bac2ddf7f2a4746a4094eaa5be30f162509cf858e7",
"a5b8788446bccb3df59751f6e1da0048acd0f7a7d4e7f3dc6e88f0f10498b0c5",
"631847b11cf027a066c445c08dfd35d9884ebf7ce0d1830061338706b9cda954",
"f84e65d3a6c4f1f06e6e24a87f122566523e395345fd57a8eb3e071dfabc91b9",
"79b489f1426580d0a9b26b52f88b443fa0d474070e455f22c033cadd2d1594a0",
"f5602a78e8f81af85eb36a4b2eacd88d21ef4994e3c8a2982ffa60a9303212a2",
"1e1584cb8f03af5ba61dfaa0b71ce40be519f74fdde908845eba0726452e2da0",
"a67169a6d6d4df8871368b68bfbf875a43a80e6b70f0196e02bed02097eb71aa",
"6a0819a62f928f761d67e539147ddc272288cb51730b6240c8265584f15c84eb",
"c725f0601869da8a51f19be1dcdcf879d7de57ba739943bbbecb6b0510bd4867",
"c2bf18cdd28082a766dceb4ec9925efd20cde34b0465918e94cc7c7b8062a454",
"a7c68dc7abfd5fa6855dd8f9a47e204af4711d0176aec7cb612402c577e47aee",
"1f632de75213303c1e2e2bd7fcd22de6a1b6e23899381364b15a7742c996d7f3",
"e2bc2f2258c08bb1b852e9ddebd108dc8744f07ffbf3030d052ab6d0202996be",
"a037ae64dc54257a68e1bfc466b6355d8fab3caecc6057aa1ea1c20fb04c12ab",
"17c3f6cac2ffed6e824619ca6aa5f439a64ab9a66512669e9c04b19dabaad4c1",
"2e200d856efc21625712480f47e33c306703afbb7dbc4a862ebd7bf65403a0b9",
"3539854d443a4d1a3784dca49b6e57d2d396fc1a28419f06b969b358d1e4f2f7",
"a9f2a9d99bf2841d4087ab7c4cccb5e4f6feb53ba0ffe10f0e9498d2438f1d89",
"9149feb5f584c2ee053596a6ee39189823eb4e34955a68f780c36a8765407aab",
"92b7c827c9c85e730388129cf61321af73c679549e2c6df95c45db7c5733b4fb",
"069b9933c262747199a3c8381634ebc757e899f211b8ba6bd1470dac50ef47fe",
"2919431ca85b132c82e402e2478c6522173bedf3de8927bca1e01865fc32ba5e",
"636104a3cb6387efc749a23210fcc0e156114f54c9935d4796adaa4c01a42f53",
"adeaaf56b8567f5a78132af62cbd4665ac4c0d34ed93a9cef7f7cf484e5645e5",
"5234d3056dd30ad9204ff4f69ba7b1b1aaa277eb0a059d97adf6b070b2cc52d3",
"c36cd1ced56c62850f54da082e90b612b32c676196a99dd4ca2688afb656c162",
"fa5a45175d1c42192285d0399ef5b2bd70950ccf90a811c2a41b82799be5fce3",
"328eab94c55de4718c2a1c458161b8bec1a7e53f459fe9170ac4a47b35c3a796",
"b5e38373974647da48c5d937ec22c9b33c5a4039f1ae59dae025b9d2eeb15b5f",
"db5d1146a3cbc9134609181f84284e4b06b3c7cb1166624abef56afe096c23d8",
"e97738242692417a95c47832060dc045740c2cc472cb19002c4b6fbc2868a3b7",
"4048523ea0babed7f90458a72c0f1a175a263175666aa85c8fc080ae766b2209",
"318f90938ff73cd01f6c1098c934d25f8b0c2a2d2aac196e598ce6a977b26fdf",
"38631cb453c3785480741f39969a2eb92a55e0c82578d607f790208b02c54b0f",
"e114b12ce35f7b015ca176c9d273b7359da126d3ae140b189611727d6da7fab8",
"470a16e8f8468778c9d384de0f88d2d2f80f8490494208c7f59d2f01f998bae1",
"e8e53c8e10f16e2400ebcccd0e44b2b84fb9d535572eaf766e9bd18f504c13eb",
"44986f459e351541b5eb297a8de945b6d8e8dbece8af46a57745de32fd207b42",
"52b3937c2e93046f407df83c69e1fa9d44cc9823960bbf2e05b5ce13bc67d27e",
"2d0367eb966d4f0da6a3842054ae534e451883224deeab67447609d54a520418",
"bc57744670aed015fc21eb450b768b12f6c56a4e1c2986fe2ffe22462926234b",
"a9cdeb9bebc3d83ed004d9f5846279b96bf46ca7d706a986b3dd03556e04ab16",
"72f2e96f881ba6765f79e658b369e3965d3e2abaa70039c236109da1b16871d8",
"bfa8c9b5f817e4662ceb6c75c6d2bd5cd3a5581336f3c43de72ea639fbf89630",
"36c76018791abbfbedab60737c5035621e8744b68ca788df878db9f6f94928ad",
"19316f657a76272f711e6b86981ff1479ef645acca36cac7bf2cbbe0e44c5841",
"eb1904fe6bd0ca4e9a5b02ccffcfe59586a76d2b2cce885bade2c2cbc4ec14b4",
"a51e618dd7d40c490c75573d0090133e619168178beec893488769f47d00c21d",
"fca09eabc9cfbfafc5c7189a94e5de4ac513374631a60ccc45d3290e3ebc81a7",
"3097d916565e77353ad25194817a487ea5b6eee381683d879f8aeafeed294e41",
"5081ed79bec72c90dba7228ac3559e75a469741deb885777bfa813d341387779",
"2a12ac0b11cb44f822dab53abd3951006237b10e1751386689fc492706686b92",
"ee2a88bd0877bd510d95351ec8884b904c03f88cc1cb1eb5c3d6d9b68a309e65",
"e1d8622ddb8b6493d479ceab011ebea4461d31f50974c76575762cf19c0be7a4",
"870dcac7a63a16b87245f2c101302e43ebce0623ca378071caaa8ca37b9d9f8b",
"0feca0bcefc165cc1e80ad48a42044141b802a2036b076a428267468832974c7",
"201d58dfa1fa65e15597d2455889bf948af9b9fb513a29b35b76a8c2edaec83b",
"3e2f02dc1c5476e7424b1cba42846fc0fc5150143c2a6aa158d2727c811b2b94",
"fc2bcafdc800f1c0098a7d36b19e38a2b8999571747d8ab83ec2b004c1d31f92",
"75b1378f2259e82c4da7fc9ac3312be6f9f95959c14f45422ffab4f282d44976",
"41aa32ebd467af200e41380033f52b479cff31b3c6a49244e7f538445a15b7e7",
"d197a080476b16cde02e2094b3218d559ff7607eefd56f0039f3f1289377316c",
"6fe569037c25b45020e11dd40b68fcfdca92d43f741eff154682f6bc97ac00e3",
"342fbf352b1315a07bb323e6e313351193a11cd82eb5c4f1c3959186d8346d77",
"7bff0dbac2b48138bd252aed1adc4257b9acaafc78bbefa4028c8b9cfe29721f",
"6800a45ef775d6e16f71cdba440046e8c3cf89e6102edd72ea365fcd3feb748d",
"338a0c04f05a4cb72ae2fd6c9f63a09a23f8058b6784be7fe89989920ea04fd1",
"d2497bbe1487fede1026ec23291efb71d90651388f72907d7ad3e7b54a98596f",
"6106a66645cb7b8ea29bc158b54364e3ea047c4e2f1eaf059b537df1b5f3e3cc",
"29c6e7ce22da78f1e70a0c44d03ee1c93a3f8a50866d95b6d2a38c75dc3f550a",
"6f5c58b7b58aa767ef5eced1a9e8b50c893571bccee09ae4c2a8ad3acdb7eec5",
"58cd143bb4d6b69d95f274e931a3c388ecfe70c08e414f4f072cade3a36b1181",
"b1b478a3e95c3db616e060f3b163b96b83d7d3fd7205b7b4c4a4c864546f3b47",
"b59a030332f38a14ddbdc20fcad4b34680a4d69818a2daea92a7caac102750cf",
"724230dc6619ddc164da1fc2034dd004fa9a4485e6dac01262c0f50ad4b4024e",
"3cfda0d9fc76d76d607221e94062af9db3597d9847993b30163c0e0263ccf0f2",
"2d5c5ec9c8257bd4aabd023158b4100c39b9904b789a54dd33239e2a31186cc1",
"0dcd3646343b2feee40cdee761162787da7636659b6ef9ce2097982beaee8c15",
"f572b035bd92f8057d6108a016285c71ac6b801846020864815c9bfe3f048b55",
"7e017fb95bf2044e3dd5984c91d077eac0054bdbdc31f7a8809fb2d2fc49a437",
"ba3a05933d16c785e4e5db840ed82e16c7ada414f5640da58cae1f8f75dbbe22",
"bfe64afb2af6c9a19588d77dc773b9614eb2dbde9abd37ccf53ab69e4f10de41",
"939d1cbe8ba291a60835e017da354e166af6347e33710b2509d586254aec0864",
"3233f9c50820f9be8193696d63aae5cef956bd3eda56276e0530c45ec798bd9f",
"3a0cc247a8eeef427c989c67581288be84b6982213235f032228f3eb49e8e876",
"e497bcd51da87c5e6abfe8f357fdfdc767032d326934ee382a2a0db5d72a577e",
"19bee468445a280956ba35226d5b276f28c52fc3516ffdb6e64e58bdd826eba1",
"71745458610170b779880f57eef9399107398c88ad8bb85e6ee90f95972147f2",
"20e629aafea7078fdd1988f4a0c8fd61a0fab333bcbb55e808b40060987412c9"
]