Electroneum
Loading...
Searching...
No Matches
blockchain_usage.cpp File Reference
#include <boost/range/adaptor/transformed.hpp>
#include <boost/algorithm/string.hpp>
#include "common/command_line.h"
#include "common/varint.h"
#include "cryptonote_core/tx_pool.h"
#include "cryptonote_core/cryptonote_core.h"
#include "cryptonote_core/blockchain.h"
#include "blockchain_db/blockchain_db.h"
#include "blockchain_db/db_types.h"
#include "version.h"
Include dependency graph for blockchain_usage.cpp:

Go to the source code of this file.

Classes

struct  output_data
struct  std::hash< output_data >
struct  reference

Namespaces

namespace  std
 STL namespace.

Macros

#define ELECTRONEUM_DEFAULT_LOG_CATEGORY   "bcutil"

Functions

int main (int argc, char *argv[])

Macro Definition Documentation

◆ ELECTRONEUM_DEFAULT_LOG_CATEGORY

#define ELECTRONEUM_DEFAULT_LOG_CATEGORY   "bcutil"

Definition at line 41 of file blockchain_usage.cpp.

Function Documentation

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 79 of file blockchain_usage.cpp.

80{
81 TRY_ENTRY();
82
84
85 std::string default_db_type = "lmdb";
86
87 std::string available_dbs = cryptonote::blockchain_db_types(", ");
88 available_dbs = "available: " + available_dbs;
89
90 uint32_t log_level = 0;
91
93
94 boost::filesystem::path output_file_path;
95
96 po::options_description desc_cmd_only("Command line options");
97 po::options_description desc_cmd_sett("Command line options and settings options");
98 const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
100 "database", available_dbs.c_str(), default_db_type
101 };
102 const command_line::arg_descriptor<bool> arg_rct_only = {"rct-only", "Only work on ringCT outputs", false};
103 const command_line::arg_descriptor<std::string> arg_input = {"input", ""};
104
107 command_line::add_arg(desc_cmd_sett, arg_log_level);
108 command_line::add_arg(desc_cmd_sett, arg_database);
109 command_line::add_arg(desc_cmd_sett, arg_rct_only);
110 command_line::add_arg(desc_cmd_sett, arg_input);
112
113 po::options_description desc_options("Allowed options");
114 desc_options.add(desc_cmd_only).add(desc_cmd_sett);
115
116 po::positional_options_description positional_options;
117 positional_options.add(arg_input.name, -1);
118
119 po::variables_map vm;
120 bool r = command_line::handle_error_helper(desc_options, [&]()
121 {
122 auto parser = po::command_line_parser(argc, argv).options(desc_options).positional(positional_options);
123 po::store(parser.run(), vm);
124 po::notify(vm);
125 return true;
126 });
127 if (! r)
128 return 1;
129
131 {
132 std::cout << "Electroneum '" << ELECTRONEUM_RELEASE_NAME << "' (v" << ELECTRONEUM_VERSION_FULL << ")" << ENDL << ENDL;
133 std::cout << desc_options << std::endl;
134 return 1;
135 }
136
137 mlog_configure(mlog_get_default_log_path("electroneum-blockchain-usage.log"), true);
138 if (!command_line::is_arg_defaulted(vm, arg_log_level))
139 mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
140 else
141 mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
142
143 LOG_PRINT_L0("Starting...");
144
146 bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
147 network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
148 bool opt_rct_only = command_line::get_arg(vm, arg_rct_only);
149
150 std::string db_type = command_line::get_arg(vm, arg_database);
152 {
153 std::cerr << "Invalid database type: " << db_type << std::endl;
154 return 1;
155 }
156
157 // If we wanted to use the memory pool, we would set up a fake_core.
158
159 // Use Blockchain instead of lower-level BlockchainDB for two reasons:
160 // 1. Blockchain has the init() method for easy setup
161 // 2. exporter needs to use get_current_blockchain_height(), get_block_id_by_height(), get_block_by_hash()
162 //
163 // cannot match blockchain_storage setup above with just one line,
164 // e.g.
165 // Blockchain* core_storage = new Blockchain(NULL);
166 // because unlike blockchain_storage constructor, which takes a pointer to
167 // tx_memory_pool, Blockchain's constructor takes tx_memory_pool object.
168 LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
169 const std::string input = command_line::get_arg(vm, arg_input);
170 std::unique_ptr<Blockchain> core_storage;
171 tx_memory_pool m_mempool(*core_storage);
172 core_storage.reset(new Blockchain(m_mempool));
173 BlockchainDB* db = new_db(db_type);
174 if (db == NULL)
175 {
176 LOG_ERROR("Attempted to use non-existent database type: " << db_type);
177 throw std::runtime_error("Attempting to use non-existent database type");
178 }
179 LOG_PRINT_L0("database: " << db_type);
180
181 const std::string filename = input;
182 LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
183
184 try
185 {
186 db->open(filename, DBF_RDONLY);
187 }
188 catch (const std::exception& e)
189 {
190 LOG_PRINT_L0("Error opening database: " << e.what());
191 return 1;
192 }
193 r = core_storage->init(db, net_type);
194
195 CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
196 LOG_PRINT_L0("Source blockchain storage initialized OK");
197
198 LOG_PRINT_L0("Building usage patterns...");
199
200 size_t done = 0;
201 std::unordered_map<output_data, std::list<reference>> outputs;
202 std::unordered_map<uint64_t,uint64_t> indices;
203
204 LOG_PRINT_L0("Reading blockchain from " << input);
205 core_storage->for_all_transactions([&](const crypto::hash &hash, const cryptonote::transaction &tx)->bool
206 {
207 const bool coinbase = tx.vin.size() == 1 && tx.vin[0].type() == typeid(txin_gen);
208 const uint64_t height = core_storage->get_db().get_tx_block_height(hash);
209
210 // create new outputs
211 for (const auto &out: tx.vout)
212 {
213 if (opt_rct_only && out.amount)
214 continue;
215 uint64_t index = indices[out.amount]++;
216 output_data od(out.amount, indices[out.amount], coinbase, height);
217 auto itb = outputs.emplace(od, std::list<reference>());
218 itb.first->first.info(coinbase, height);
219 }
220
221 for (const auto &in: tx.vin)
222 {
223 if (in.type() != typeid(txin_to_key))
224 continue;
225 const auto &txin = boost::get<txin_to_key>(in);
226 if (opt_rct_only && txin.amount != 0)
227 continue;
228
229 const std::vector<uint64_t> absolute = cryptonote::relative_output_offsets_to_absolute(txin.key_offsets);
230 for (size_t n = 0; n < txin.key_offsets.size(); ++n)
231 {
232 output_data od(txin.amount, absolute[n], coinbase, height);
233 outputs[od].push_back(reference(height, txin.key_offsets.size(), n));
234 }
235 }
236 return true;
237 }, true);
238
239 std::unordered_map<uint64_t, uint64_t> counts;
240 size_t total = 0;
241 for (const auto &out: outputs)
242 {
243 counts[out.second.size()]++;
244 total++;
245 }
246 if (total > 0)
247 {
248 for (const auto &c: counts)
249 {
250 float percent = 100.f * c.second / total;
251 MINFO(std::to_string(c.second) << " outputs used " << c.first << " times (" << percent << "%)");
252 }
253 }
254 else
255 {
256 MINFO("No outputs to process");
257 }
258
259 LOG_PRINT_L0("Blockchain usage exported OK");
260 return 0;
261
262 CATCH_ENTRY("Export error", 1);
263}
uint64_t height
#define DBF_RDONLY
The BlockchainDB backing store interface declaration/contract.
virtual void open(const std::string &filename, const int db_flags=0)=0
open a db, or create it if necessary.
Transaction pool, handles transactions which are not part of a block.
Definition tx_pool.h:95
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size=MAX_LOG_FILE_SIZE, const std::size_t max_log_files=MAX_LOG_FILES)
Definition mlog.cpp:148
#define CATCH_ENTRY(location, return_val)
std::string mlog_get_default_log_path(const char *default_filename)
Definition mlog.cpp:72
void mlog_set_log(const char *log)
Definition mlog.cpp:288
#define ENDL
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
#define LOG_ERROR(x)
Definition misc_log_ex.h:98
#define MINFO(x)
Definition misc_log_ex.h:75
#define TRY_ENTRY()
#define LOG_PRINT_L0(x)
Definition misc_log_ex.h:99
void add_arg(boost::program_options::options_description &description, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg, bool unique=true)
const arg_descriptor< bool > arg_help
bool is_arg_defaulted(const boost::program_options::variables_map &vm, const arg_descriptor< T, required, dependent, NUM_DEPS > &arg)
bool handle_error_helper(const boost::program_options::options_description &desc, F parser)
T get_arg(const boost::program_options::variables_map &vm, const arg_descriptor< T, false, true > &arg)
POD_CLASS hash
Definition hash.h:50
std::vector< uint64_t > relative_output_offsets_to_absolute(const std::vector< uint64_t > &off)
const command_line::arg_descriptor< bool, false > arg_testnet_on
BlockchainDB * new_db(const std::string &db_type)
bool blockchain_valid_db_type(const std::string &db_type)
const command_line::arg_descriptor< bool, false > arg_stagenet_on
std::string blockchain_db_types(const std::string &sep)
const command_line::arg_descriptor< std::string > arg_log_level
bool set_module_name_and_folder(const std::string &path_to_process_)
bool on_startup()
Definition util.cpp:778
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
const char *const ELECTRONEUM_RELEASE_NAME
const char *const ELECTRONEUM_VERSION_FULL
Here is the call graph for this function: