{"id":16153708,"url":"https://github.com/moneroexamples/block-access-time","last_synced_at":"2025-07-18T04:34:29.246Z","repository":{"id":70343430,"uuid":"46249384","full_name":"moneroexamples/block-access-time","owner":"moneroexamples","description":null,"archived":false,"fork":false,"pushed_at":"2016-11-17T03:58:06.000Z","size":71,"stargazers_count":3,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-30T12:51:14.945Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moneroexamples.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-11-16T03:19:00.000Z","updated_at":"2021-06-05T17:58:52.000Z","dependencies_parsed_at":"2023-03-13T20:24:05.954Z","dependency_job_id":null,"html_url":"https://github.com/moneroexamples/block-access-time","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moneroexamples%2Fblock-access-time","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moneroexamples%2Fblock-access-time/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moneroexamples%2Fblock-access-time/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moneroexamples%2Fblock-access-time/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moneroexamples","download_url":"https://codeload.github.com/moneroexamples/block-access-time/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251645600,"owners_count":21620772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-10T01:14:14.711Z","updated_at":"2025-04-30T05:20:21.578Z","avatar_url":"https://github.com/moneroexamples.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Measure block access time\nWhile working on another example, I've noticed that access time to some\nmonero blocks, especially early ones, using `Blockchain::get_block_by_hash`,\nis very long. Thus, I wanted check this time for all blocks in the blockchain.\n\nAs a result of this, this example was created showing how to loop through all\nblocks in lmdb blockchain, and extract some basic information about each block,\nas well as measure its access/search time, into an output csv file.\n\n## Pre-requisites\n\nEverything here was done and tested on\nUbuntu 14.04 x86_64 and Ubuntu 15.10 x86_64.\n\nInstruction for Monero compilation:\n - [Ubuntu 14.04 x86_64](http://moneroexamples.github.io/compile-monero-ubuntu/)\n - [Ubuntu 15.10 x86_64](http://moneroexamples.github.io/compile-monero-ubuntu-1510/)\n\n\nMonero source code compilation and setup are same as [here](http://moneroexamples.github.io/access-blockchain-in-cpp/).\n\n\n## C++: main.cpp\n\n```c++\nint main(int ac, const char* av[]) {\n\n    // get command line options\n    xmreg::CmdLineOptions opts {ac, av};\n\n    auto help_opt = opts.get_option\u003cbool\u003e(\"help\");\n\n    // if help was chosen, display help text and finish\n    if (*help_opt)\n    {\n        return 0;\n    }\n\n    // get other options\n    auto start_height_opt = opts.get_option\u003csize_t\u003e(\"start-height\");\n    auto out_csv_file_opt = opts.get_option\u003cstring\u003e(\"out-csv-file\");\n    auto bc_path_opt      = opts.get_option\u003cstring\u003e(\"bc-path\");\n\n\n    // default path to monero folder\n    // on linux this is /home/\u003cusername\u003e/.bitmonero\n    string default_monero_dir = tools::get_default_data_dir();\n\n    // the default folder of the lmdb blockchain database\n    // is therefore as follows\n    string default_lmdb_dir   = default_monero_dir + \"/lmdb\";\n\n    // get the program command line options, or\n    // some default values for quick check\n    size_t start_height  = start_height_opt ? *start_height_opt : 0;\n    string out_csv_file  = out_csv_file_opt ? *out_csv_file_opt : \"/tmp/block_access_time.csv\";\n    path blockchain_path = bc_path_opt ? path(*bc_path_opt) : path(default_lmdb_dir);\n\n\n    if (!is_directory(blockchain_path))\n    {\n        cerr \u003c\u003c \"Given path \\\"\" \u003c\u003c blockchain_path   \u003c\u003c \"\\\" \"\n             \u003c\u003c \"is not a folder or does not exist\" \u003c\u003c \" \"\n             \u003c\u003c endl;\n        return 1;\n    }\n\n    blockchain_path = xmreg::remove_trailing_path_separator(blockchain_path);\n\n    cout \u003c\u003c \"Blockchain path: \" \u003c\u003c blockchain_path \u003c\u003c endl;\n\n    // enable basic monero log output\n    uint32_t log_level = 0;\n    epee::log_space::get_set_log_detalisation_level(true, log_level);\n    epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL);\n\n\n    // create instance of our MicroCore\n    xmreg::MicroCore mcore;\n\n    // initialize the core using the blockchain path\n    if (!mcore.init(blockchain_path.string()))\n    {\n        cerr \u003c\u003c \"Error accessing blockchain.\" \u003c\u003c endl;\n        return 1;\n    }\n\n    // get the highlevel cryptonote::Blockchain object to interact\n    // with the blockchain lmdb database\n    cryptonote::Blockchain\u0026 core_storage = mcore.get_core();\n\n    // get the current blockchain height. Just to check\n    // if it reads ok.\n    uint64_t height = core_storage.get_current_blockchain_height();\n\n    if (start_height \u003e height)\n    {\n        cerr \u003c\u003c \"Given height is greater than blockchain height\" \u003c\u003c endl;\n        return 1;\n    }\n\n\n    cout \u003c\u003c \"Current blockchain height: \" \u003c\u003c height \u003c\u003c endl;\n\n\n    // output csv file\n    csv::ofstream csv_os {out_csv_file.c_str()};\n\n    if (!csv_os.is_open())\n    {\n        cerr \u003c\u003c \"Cant open file: \" \u003c\u003c out_csv_file \u003c\u003c endl;\n        return 1;\n    }\n\n    cout \u003c\u003c \"Csv file: \" \u003c\u003c  out_csv_file \u003c\u003c \" opened for wrting results.\" \u003c\u003c endl;\n\n    // write csv header\n    csv_os \u003c\u003c \"Height\" \u003c\u003c \"Timestamp\" \u003c\u003c \"Access_time\" \u003c\u003c \"Size\"\n           \u003c\u003c \"Hash\" \u003c\u003c \"No_tx\" \u003c\u003c \"Reward\" \u003c\u003c \"Dificulty\" \u003c\u003c NEWLINE;\n\n    // show command line output for everth i-th block\n    const uint64_t EVERY_ith_BLOCK {2000};\n\n    for (uint64_t i = start_height; i \u003c height; ++i) {\n\n        // show every nth output, just to give\n        // a console some break\n        if (i % EVERY_ith_BLOCK == 0)\n            cout \u003c\u003c \"Analysing block \" \u003c\u003c i \u003c\u003c  \"/\" \u003c\u003c height \u003c\u003c endl;\n\n\n\n        crypto::hash block_id;\n\n        try\n        {\n            // get block hash to be used to for the search\n            // in the next step\n            block_id = core_storage.get_block_id_by_height(i);\n        }\n        catch (const exception\u0026 e)\n        {\n            cerr \u003c\u003c e.what() \u003c\u003c endl;\n            continue;\n        }\n\n\n        cryptonote::block blk;\n\n        try\n        {\n            // measure time of accessing ith block from the blockchain\n            auto start = chrono::system_clock::now();\n            //blk = core_storage.get_db().get_block_from_height(i); // \u003c-- alternative, faster\n            core_storage.get_block_by_hash(block_id, blk);\n            auto duration = chrono::duration_cast\u003cchrono::nanoseconds\u003e(chrono::system_clock::now() - start);\n\n            // get block size\n            size_t blk_size = core_storage.get_db().get_block_size(i);\n\n            if (i % EVERY_ith_BLOCK == 0)\n                cout \u003c\u003c \" - \" \u003c\u003c \"access time: \" \u003c\u003c duration.count() \u003c\u003c \" ns.\" \u003c\u003c endl;\n\n            // save measured data to the output csv file\n            csv_os \u003c\u003c i \u003c\u003c xmreg::timestamp_to_str(blk.timestamp)\n                   \u003c\u003c duration.count() \u003c\u003c blk_size\n                   \u003c\u003c core_storage.get_block_id_by_height(i)\n                   \u003c\u003c blk.tx_hashes.size()\n                   \u003c\u003c cryptonote::print_money(mcore.get_block_reward(blk))\n                   \u003c\u003c core_storage.get_db().get_block_difficulty(i)\n                   \u003c\u003c NEWLINE;\n        }\n        catch (const exception\u0026 e)\n        {\n            cerr \u003c\u003c e.what() \u003c\u003c endl;\n            continue;\n        }\n\n\n    } // for (uint64_t i = 0; i \u003c height; ++i)\n\n\n    // colose the output csv file\n    csv_os.flush();\n    csv_os.close();\n\n    cout \u003c\u003c \"\\nCsv saved as: \" \u003c\u003c out_csv_file \u003c\u003c endl;\n\n    cout \u003c\u003c \"\\nEnd of program.\" \u003c\u003c endl;\n\n    return 0;\n}\n```\n\n## Results\n\n- The resulted csv file can be seen [here](https://mega.nz/#!P4cWWTLK!Eb5m4q4f5Tx-5p5FNMwF7cv0ckvPTX5Hy5fqGn7VFm4).\n\n- Screenshot of the results is [here](http://i.imgur.com/BU0RBYs.png).\n\n- The plot of log of block access time against block number is [here](http://i.imgur.com/2xmAF0c.png).\n\nFrom the csv and data, it can be seen that there is very large\nconcentration of very long times up to block of about 100k. This\nresults in very slow recovery of your deterministic wallet, when\nthe blocks in this range are being scanned for your transactions.\n\n\n## Compile this example\nThe dependencies are same as those for Monero, so I assume Monero compiles\ncorrectly. If so then to download and compile this example, the following\nsteps can be executed:\n\n```bash\n# download the source code\ngit clone https://github.com/moneroexamples/block-access-time\n\n# enter the downloaded sourced code folder\ncd block-access-time\n\n# create the makefile\ncmake .\n\n# compile\nmake\n```\n\nAfter this, `blkaccesstime` executable file should be present in access-blockchain-in-cpp\nfolder. How to use it, can be seen in the above example outputs.\n\n\n## How can you help?\n\nConstructive criticism, code and website edits are always good. They can be made through github.\n\nSome Monero are also welcome:\n```\n48daf1rG3hE1Txapcsxh6WXNe9MLNKtu7W7tKTivtSoVLHErYzvdcpea2nSTgGkz66RFP4GKVAsTV14v6G3oddBTHfxP6tU\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoneroexamples%2Fblock-access-time","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoneroexamples%2Fblock-access-time","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoneroexamples%2Fblock-access-time/lists"}