100{
102
104
105 std::string default_db_type = "lmdb";
106
108 available_dbs = "available: " + available_dbs;
109
111
113
114 po::options_description desc_cmd_only("Command line options");
115 po::options_description desc_cmd_sett("Command line options and settings options");
118 "database", available_dbs.c_str(), default_db_type
119 };
123
133
134 po::options_description desc_options("Allowed options");
135 desc_options.add(desc_cmd_only).add(desc_cmd_sett);
136
137 po::variables_map vm;
139 {
140 auto parser = po::command_line_parser(argc, argv).options(desc_options);
141 po::store(parser.run(), vm);
142 po::notify(vm);
143 return true;
144 });
145 if (! r)
146 return 1;
147
149 {
151 std::cout << desc_options << std::endl;
152 return 1;
153 }
154
158 else
159 mlog_set_log(std::string(std::to_string(log_level) +
",bcutil:INFO").c_str());
160
162
169
172 {
173 std::cerr << "Invalid database type: " << db_type << std::endl;
174 return 1;
175 }
176
178
179 LOG_PRINT_L0(
"Initializing source blockchain (BlockchainDB)");
180 std::unique_ptr<Blockchain> core_storage;
182 core_storage.reset(
new Blockchain(m_mempool));
184 if (db == NULL)
185 {
186 LOG_ERROR(
"Attempted to use non-existent database type: " << db_type);
187 throw std::runtime_error("Attempting to use non-existent database type");
188 }
190
191 const std::string filename = (boost::filesystem::path(opt_data_dir) / db->
get_db_name()).
string();
192 LOG_PRINT_L0(
"Loading blockchain from folder " << filename <<
" ...");
193
194 try
195 {
196 db->
open(filename, 0);
197 }
198 catch (const std::exception& e)
199 {
201 return 1;
202 }
203 r = core_storage->init(db, net_type);
204
206 LOG_PRINT_L0(
"Source blockchain storage initialized OK");
207
208 std::map<uint64_t, uint64_t> known_spent_outputs;
209 if (input.empty())
210 {
211 std::map<uint64_t, std::pair<uint64_t, uint64_t>> outputs;
212
215 const bool miner_tx = tx.
vin.size() == 1 && tx.
vin[0].type() ==
typeid(
txin_gen);
216 for (
const auto &in: tx.
vin)
217 {
219 continue;
220 const auto &txin = boost::get<txin_to_key>(in);
221 if (txin.amount == 0)
222 continue;
223
224 outputs[txin.amount].second++;
225 }
226
227 for (
const auto &out: tx.
vout)
228 {
231 continue;
232
233 outputs[amount].first++;
234 }
235 return true;
236 }, true);
237
238 for (const auto &i: outputs)
239 {
240 known_spent_outputs[i.first] = i.second.second;
241 }
242 }
243 else
244 {
246 known_spent_outputs = load_outputs(input);
247 }
248
250
251 bool stop_requested = false;
253 stop_requested = true;
254 });
255
257
258 size_t num_total_outputs = 0, num_prunable_outputs = 0, num_known_spent_outputs = 0, num_eligible_outputs = 0, num_eligible_known_spent_outputs = 0;
259 for (auto i = known_spent_outputs.begin(); i != known_spent_outputs.end(); ++i)
260 {
262 num_total_outputs += num_outputs;
263 num_known_spent_outputs += i->second;
265 {
266 if (opt_verbose)
267 MINFO(
"Ignoring output value " << i->first <<
", with " << num_outputs <<
" outputs");
268 continue;
269 }
270 num_eligible_outputs += num_outputs;
271 num_eligible_known_spent_outputs += i->second;
272 if (opt_verbose)
273 MINFO(i->first <<
": " << i->second <<
"/" << num_outputs);
274 if (num_outputs > i->second)
275 continue;
276 if (num_outputs && num_outputs < i->second)
277 {
278 MERROR(
"More outputs are spent than known for amount " << i->first <<
", not touching");
279 continue;
280 }
281 if (opt_verbose)
282 MINFO(
"Pruning data for " << num_outputs <<
" outputs");
283 if (!opt_dry_run)
285 num_prunable_outputs += i->second;
286 }
287
289
290 MINFO(
"Total outputs: " << num_total_outputs);
291 MINFO(
"Known spent outputs: " << num_known_spent_outputs);
292 MINFO(
"Eligible outputs: " << num_eligible_outputs);
293 MINFO(
"Eligible known spent outputs: " << num_eligible_known_spent_outputs);
294 MINFO(
"Prunable outputs: " << num_prunable_outputs);
295
297 core_storage->deinit();
298 return 0;
299
301}
The BlockchainDB backing store interface declaration/contract.
virtual void prune_outputs(uint64_t amount)=0
prune output data for the given amount
virtual void batch_stop()=0
ends a batch transaction
virtual bool for_all_transactions(std::function< bool(const crypto::hash &, const cryptonote::transaction &)>, bool pruned) const =0
runs a function over all transactions stored
virtual std::string get_db_name() const =0
gets the name of the folder the BlockchainDB's file(s) should be in
virtual uint64_t get_num_outputs(const uint64_t &amount) const =0
fetches the number of outputs of a given amount
virtual bool batch_start(uint64_t batch_num_blocks=0, uint64_t batch_bytes=0)=0
tells the BlockchainDB to start a new "batch" of blocks
virtual void open(const std::string &filename, const int db_flags=0)=0
open a db, or create it if necessary.
std::vector< txin_v > vin
std::vector< tx_out > vout
Transaction pool, handles transactions which are not part of a block.
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)
#define CATCH_ENTRY(location, return_val)
std::string mlog_get_default_log_path(const char *default_filename)
void mlog_set_log(const char *log)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message)
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)
const command_line::arg_descriptor< std::string, false, true, 2 > arg_data_dir
bool is_valid_decomposed_amount(uint64_t amount)
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
unsigned __int64 uint64_t
const char *const ELECTRONEUM_RELEASE_NAME
const char *const ELECTRONEUM_VERSION_FULL