mirror of
https://github.com/monero-project/monero.git
synced 2024-11-18 10:01:02 +00:00
blockchain_blackball: support pre-v2 databases
This commit is contained in:
parent
daa6cc7d73
commit
846190fd18
1 changed files with 123 additions and 79 deletions
|
@ -161,6 +161,13 @@ static int compare_hash32(const MDB_val *a, const MDB_val *b)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int compare_uint64(const MDB_val *a, const MDB_val *b)
|
||||||
|
{
|
||||||
|
const uint64_t va = *(const uint64_t *)a->mv_data;
|
||||||
|
const uint64_t vb = *(const uint64_t *)b->mv_data;
|
||||||
|
return (va < vb) ? -1 : va > vb;
|
||||||
|
}
|
||||||
|
|
||||||
static int compare_double64(const MDB_val *a, const MDB_val *b)
|
static int compare_double64(const MDB_val *a, const MDB_val *b)
|
||||||
{
|
{
|
||||||
const uint64_t va = *(const uint64_t*) a->mv_data;
|
const uint64_t va = *(const uint64_t*) a->mv_data;
|
||||||
|
@ -308,7 +315,7 @@ static std::vector<uint64_t> decompress_ring(const std::string &s)
|
||||||
return ring;
|
return ring;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool for_all_transactions(const std::string &filename, uint64_t &start_idx, const std::function<bool(const cryptonote::transaction_prefix&)> &f)
|
static bool for_all_transactions(const std::string &filename, uint64_t &start_idx, uint64_t &n_txes, const std::function<bool(const cryptonote::transaction_prefix&)> &f)
|
||||||
{
|
{
|
||||||
MDB_env *env;
|
MDB_env *env;
|
||||||
MDB_dbi dbi;
|
MDB_dbi dbi;
|
||||||
|
@ -316,6 +323,8 @@ static bool for_all_transactions(const std::string &filename, uint64_t &start_id
|
||||||
MDB_cursor *cur;
|
MDB_cursor *cur;
|
||||||
int dbr;
|
int dbr;
|
||||||
bool tx_active = false;
|
bool tx_active = false;
|
||||||
|
MDB_val k;
|
||||||
|
MDB_val v;
|
||||||
|
|
||||||
dbr = mdb_env_create(&env);
|
dbr = mdb_env_create(&env);
|
||||||
if (dbr) throw std::runtime_error("Failed to create LDMB environment: " + std::string(mdb_strerror(dbr)));
|
if (dbr) throw std::runtime_error("Failed to create LDMB environment: " + std::string(mdb_strerror(dbr)));
|
||||||
|
@ -337,9 +346,11 @@ static bool for_all_transactions(const std::string &filename, uint64_t &start_id
|
||||||
if (dbr) throw std::runtime_error("Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
|
if (dbr) throw std::runtime_error("Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
|
||||||
dbr = mdb_cursor_open(txn, dbi, &cur);
|
dbr = mdb_cursor_open(txn, dbi, &cur);
|
||||||
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
|
if (dbr) throw std::runtime_error("Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
|
||||||
|
MDB_stat stat;
|
||||||
|
dbr = mdb_stat(txn, dbi, &stat);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to query m_block_info: " + std::string(mdb_strerror(dbr)));
|
||||||
|
n_txes = stat.ms_entries;
|
||||||
|
|
||||||
MDB_val k;
|
|
||||||
MDB_val v;
|
|
||||||
bool fret = true;
|
bool fret = true;
|
||||||
|
|
||||||
k.mv_size = sizeof(uint64_t);
|
k.mv_size = sizeof(uint64_t);
|
||||||
|
@ -630,6 +641,90 @@ static void add_key_image(MDB_txn *txn, const output_data &od, const crypto::key
|
||||||
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to set outputs: " + std::string(mdb_strerror(dbr)));
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to set outputs: " + std::string(mdb_strerror(dbr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void open_db(const std::string &filename, MDB_env **env, MDB_txn **txn, MDB_cursor **cur, MDB_dbi *dbi)
|
||||||
|
{
|
||||||
|
tools::create_directories_if_necessary(filename);
|
||||||
|
|
||||||
|
int flags = MDB_RDONLY;
|
||||||
|
if (db_flags & DBF_FAST)
|
||||||
|
flags |= MDB_NOSYNC;
|
||||||
|
if (db_flags & DBF_FASTEST)
|
||||||
|
flags |= MDB_NOSYNC | MDB_WRITEMAP | MDB_MAPASYNC;
|
||||||
|
|
||||||
|
int dbr = mdb_env_create(env);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LDMB environment: " + std::string(mdb_strerror(dbr)));
|
||||||
|
dbr = mdb_env_set_maxdbs(*env, 1);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to set max env dbs: " + std::string(mdb_strerror(dbr)));
|
||||||
|
const std::string actual_filename = filename;
|
||||||
|
MINFO("Opening monero blockchain at " << actual_filename);
|
||||||
|
dbr = mdb_env_open(*env, actual_filename.c_str(), flags, 0664);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open rings database file '"
|
||||||
|
+ actual_filename + "': " + std::string(mdb_strerror(dbr)));
|
||||||
|
|
||||||
|
dbr = mdb_txn_begin(*env, NULL, MDB_RDONLY, txn);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
|
||||||
|
|
||||||
|
dbr = mdb_dbi_open(*txn, "output_amounts", MDB_CREATE | MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, dbi);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
|
||||||
|
mdb_set_dupsort(*txn, *dbi, compare_uint64);
|
||||||
|
|
||||||
|
dbr = mdb_cursor_open(*txn, *dbi, cur);
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB cursor: " + std::string(mdb_strerror(dbr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_db(MDB_env *env, MDB_txn *txn, MDB_cursor *cur, MDB_dbi dbi)
|
||||||
|
{
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
mdb_cursor_close(cur);
|
||||||
|
mdb_dbi_close(env, dbi);
|
||||||
|
mdb_env_close(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
static crypto::public_key get_output_key(MDB_cursor *cur, uint64_t amount, uint64_t offset)
|
||||||
|
{
|
||||||
|
MDB_val k = { sizeof(amount), (void*)&amount }, v = { sizeof(offset), (void*)&offset };
|
||||||
|
int dbr = mdb_cursor_get(cur, &k, &v, MDB_GET_BOTH);
|
||||||
|
if (dbr) throw std::runtime_error("Output key not found: " + std::string(mdb_strerror(dbr)));
|
||||||
|
return *(const crypto::public_key*)(((const char*)v.mv_data) + sizeof(uint64_t) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static crypto::hash get_genesis_block_hash(const std::string &filename)
|
||||||
|
{
|
||||||
|
MDB_env *env;
|
||||||
|
MDB_dbi dbi;
|
||||||
|
MDB_txn *txn;
|
||||||
|
int dbr;
|
||||||
|
bool tx_active = false;
|
||||||
|
|
||||||
|
dbr = mdb_env_create(&env);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to create LDMB environment: " + std::string(mdb_strerror(dbr)));
|
||||||
|
dbr = mdb_env_set_maxdbs(env, 1);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to set max env dbs: " + std::string(mdb_strerror(dbr)));
|
||||||
|
const std::string actual_filename = filename;
|
||||||
|
dbr = mdb_env_open(env, actual_filename.c_str(), 0, 0664);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to open rings database file '"
|
||||||
|
+ actual_filename + "': " + std::string(mdb_strerror(dbr)));
|
||||||
|
|
||||||
|
dbr = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
|
||||||
|
epee::misc_utils::auto_scope_leave_caller txn_dtor = epee::misc_utils::create_scope_leave_handler([&](){if (tx_active) mdb_txn_abort(txn);});
|
||||||
|
tx_active = true;
|
||||||
|
|
||||||
|
dbr = mdb_dbi_open(txn, "block_info", MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, &dbi);
|
||||||
|
mdb_set_dupsort(txn, dbi, compare_uint64);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
|
||||||
|
uint64_t zero = 0;
|
||||||
|
MDB_val k = { sizeof(uint64_t), (void*)&zero}, v;
|
||||||
|
dbr = mdb_get(txn, dbi, &k, &v);
|
||||||
|
if (dbr) throw std::runtime_error("Failed to retrieve genesis block: " + std::string(mdb_strerror(dbr)));
|
||||||
|
crypto::hash genesis_block_hash = *(const crypto::hash*)(((const uint64_t*)v.mv_data) + 5);
|
||||||
|
mdb_dbi_close(env, dbi);
|
||||||
|
mdb_txn_abort(txn);
|
||||||
|
mdb_env_close(env);
|
||||||
|
tx_active = false;
|
||||||
|
return genesis_block_hash;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
|
@ -649,17 +744,9 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
po::options_description desc_cmd_only("Command line options");
|
po::options_description desc_cmd_only("Command line options");
|
||||||
po::options_description desc_cmd_sett("Command line options and settings options");
|
po::options_description desc_cmd_sett("Command line options and settings options");
|
||||||
const command_line::arg_descriptor<std::string, false, true, 2> arg_blackball_db_dir = {
|
const command_line::arg_descriptor<std::string> arg_blackball_db_dir = {
|
||||||
"blackball-db-dir", "Specify blackball database directory",
|
"blackball-db-dir", "Specify blackball database directory",
|
||||||
get_default_db_path(),
|
get_default_db_path(),
|
||||||
{{ &arg_testnet_on, &arg_stagenet_on }},
|
|
||||||
[](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string {
|
|
||||||
if (testnet_stagenet[0])
|
|
||||||
return (boost::filesystem::path(val) / "testnet").string();
|
|
||||||
else if (testnet_stagenet[1])
|
|
||||||
return (boost::filesystem::path(val) / "stagenet").string();
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
|
const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
|
||||||
const command_line::arg_descriptor<std::string> arg_database = {
|
const command_line::arg_descriptor<std::string> arg_database = {
|
||||||
|
@ -674,8 +761,6 @@ int main(int argc, char* argv[])
|
||||||
};
|
};
|
||||||
|
|
||||||
command_line::add_arg(desc_cmd_sett, arg_blackball_db_dir);
|
command_line::add_arg(desc_cmd_sett, arg_blackball_db_dir);
|
||||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
|
|
||||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
|
|
||||||
command_line::add_arg(desc_cmd_sett, arg_log_level);
|
command_line::add_arg(desc_cmd_sett, arg_log_level);
|
||||||
command_line::add_arg(desc_cmd_sett, arg_database);
|
command_line::add_arg(desc_cmd_sett, arg_database);
|
||||||
command_line::add_arg(desc_cmd_sett, arg_rct_only);
|
command_line::add_arg(desc_cmd_sett, arg_rct_only);
|
||||||
|
@ -715,9 +800,6 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
LOG_PRINT_L0("Starting...");
|
LOG_PRINT_L0("Starting...");
|
||||||
|
|
||||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
|
||||||
bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
|
|
||||||
network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
|
|
||||||
output_file_path = command_line::get_arg(vm, arg_blackball_db_dir);
|
output_file_path = command_line::get_arg(vm, arg_blackball_db_dir);
|
||||||
bool opt_rct_only = command_line::get_arg(vm, arg_rct_only);
|
bool opt_rct_only = command_line::get_arg(vm, arg_rct_only);
|
||||||
|
|
||||||
|
@ -735,58 +817,12 @@ int main(int argc, char* argv[])
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we wanted to use the memory pool, we would set up a fake_core.
|
|
||||||
|
|
||||||
// Use Blockchain instead of lower-level BlockchainDB for two reasons:
|
|
||||||
// 1. Blockchain has the init() method for easy setup
|
|
||||||
// 2. exporter needs to use get_current_blockchain_height(), get_block_id_by_height(), get_block_by_hash()
|
|
||||||
//
|
|
||||||
// cannot match blockchain_storage setup above with just one line,
|
|
||||||
// e.g.
|
|
||||||
// Blockchain* core_storage = new Blockchain(NULL);
|
|
||||||
// because unlike blockchain_storage constructor, which takes a pointer to
|
|
||||||
// tx_memory_pool, Blockchain's constructor takes tx_memory_pool object.
|
|
||||||
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
|
|
||||||
const std::vector<std::string> inputs = command_line::get_arg(vm, arg_inputs);
|
const std::vector<std::string> inputs = command_line::get_arg(vm, arg_inputs);
|
||||||
if (inputs.empty())
|
if (inputs.empty())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("No inputs given");
|
LOG_PRINT_L0("No inputs given");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::vector<std::unique_ptr<Blockchain>> core_storage(inputs.size());
|
|
||||||
Blockchain *blockchain = NULL;
|
|
||||||
tx_memory_pool m_mempool(*blockchain);
|
|
||||||
for (size_t n = 0; n < inputs.size(); ++n)
|
|
||||||
{
|
|
||||||
core_storage[n].reset(new Blockchain(m_mempool));
|
|
||||||
|
|
||||||
BlockchainDB* db = new_db(db_type);
|
|
||||||
if (db == NULL)
|
|
||||||
{
|
|
||||||
LOG_ERROR("Attempted to use non-existent database type: " << db_type);
|
|
||||||
throw std::runtime_error("Attempting to use non-existent database type");
|
|
||||||
}
|
|
||||||
LOG_PRINT_L0("database: " << db_type);
|
|
||||||
|
|
||||||
std::string filename = (boost::filesystem::path(inputs[n]) / db->get_db_name()).string();
|
|
||||||
while (boost::ends_with(filename, "/") || boost::ends_with(filename, "\\"))
|
|
||||||
filename.pop_back();
|
|
||||||
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
db->open(filename, DBF_RDONLY);
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
LOG_PRINT_L0("Error opening database: " << e.what());
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
r = core_storage[n]->init(db, net_type);
|
|
||||||
|
|
||||||
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
|
|
||||||
LOG_PRINT_L0("Source blockchain storage initialized OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string cache_dir = (output_file_path / "blackball-cache").string();
|
const std::string cache_dir = (output_file_path / "blackball-cache").string();
|
||||||
init(cache_dir);
|
init(cache_dir);
|
||||||
|
@ -797,8 +833,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
const uint64_t start_blackballed_outputs = get_num_spent_outputs(false);
|
const uint64_t start_blackballed_outputs = get_num_spent_outputs(false);
|
||||||
|
|
||||||
cryptonote::block b = core_storage[0]->get_db().get_block_from_height(0);
|
tools::ringdb ringdb(output_file_path.string(), epee::string_tools::pod_to_hex(get_genesis_block_hash(inputs[0])));
|
||||||
tools::ringdb ringdb(output_file_path.string(), epee::string_tools::pod_to_hex(get_block_hash(b)));
|
|
||||||
|
|
||||||
bool stop_requested = false;
|
bool stop_requested = false;
|
||||||
tools::signal_handler::install([&stop_requested](int type) {
|
tools::signal_handler::install([&stop_requested](int type) {
|
||||||
|
@ -808,6 +843,13 @@ int main(int argc, char* argv[])
|
||||||
int dbr = resize_env(cache_dir.c_str());
|
int dbr = resize_env(cache_dir.c_str());
|
||||||
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to resize LMDB database: " + std::string(mdb_strerror(dbr)));
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to resize LMDB database: " + std::string(mdb_strerror(dbr)));
|
||||||
|
|
||||||
|
// open first db
|
||||||
|
MDB_env *env0;
|
||||||
|
MDB_txn *txn0;
|
||||||
|
MDB_dbi dbi0;
|
||||||
|
MDB_cursor *cur0;
|
||||||
|
open_db(inputs[0], &env0, &txn0, &cur0, &dbi0);
|
||||||
|
|
||||||
for (size_t n = 0; n < inputs.size(); ++n)
|
for (size_t n = 0; n < inputs.size(); ++n)
|
||||||
{
|
{
|
||||||
const std::string canonical = boost::filesystem::canonical(inputs[n]).string();
|
const std::string canonical = boost::filesystem::canonical(inputs[n]).string();
|
||||||
|
@ -817,10 +859,10 @@ int main(int argc, char* argv[])
|
||||||
int dbr = mdb_txn_begin(env, NULL, 0, &txn);
|
int dbr = mdb_txn_begin(env, NULL, 0, &txn);
|
||||||
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
|
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
|
||||||
size_t records = 0;
|
size_t records = 0;
|
||||||
const uint64_t n_txes = core_storage[n]->get_db().get_tx_count();
|
const std::string filename = inputs[n];
|
||||||
const std::string filename = (boost::filesystem::path(inputs[n]) / core_storage[n]->get_db().get_db_name()).string();
|
|
||||||
std::vector<crypto::public_key> blackballs;
|
std::vector<crypto::public_key> blackballs;
|
||||||
for_all_transactions(filename, start_idx, [&](const cryptonote::transaction_prefix &tx)->bool
|
uint64_t n_txes;
|
||||||
|
for_all_transactions(filename, start_idx, n_txes, [&](const cryptonote::transaction_prefix &tx)->bool
|
||||||
{
|
{
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
for (const auto &in: tx.vin)
|
for (const auto &in: tx.vin)
|
||||||
|
@ -842,34 +884,34 @@ int main(int argc, char* argv[])
|
||||||
uint64_t instances = get_ring_instances(txn, new_ring);
|
uint64_t instances = get_ring_instances(txn, new_ring);
|
||||||
++instances;
|
++instances;
|
||||||
set_ring_instances(txn, new_ring, instances);
|
set_ring_instances(txn, new_ring, instances);
|
||||||
if (ring_size == 1)
|
if (n == 0 && ring_size == 1)
|
||||||
{
|
{
|
||||||
const crypto::public_key pkey = core_storage[n]->get_output_key(txin.amount, absolute[0]);
|
const crypto::public_key pkey = get_output_key(cur0, txin.amount, absolute[0]);
|
||||||
MINFO("Blackballing output " << pkey << ", due to being used in a 1-ring");
|
MINFO("Blackballing output " << pkey << ", due to being used in a 1-ring");
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
blackballs.push_back(pkey);
|
blackballs.push_back(pkey);
|
||||||
add_spent_output(txn, output_data(txin.amount, absolute[0]), true);
|
add_spent_output(txn, output_data(txin.amount, absolute[0]), true);
|
||||||
}
|
}
|
||||||
else if (instances == new_ring.size())
|
else if (n == 0 && instances == new_ring.size())
|
||||||
{
|
{
|
||||||
for (size_t o = 0; o < new_ring.size(); ++o)
|
for (size_t o = 0; o < new_ring.size(); ++o)
|
||||||
{
|
{
|
||||||
const crypto::public_key pkey = core_storage[n]->get_output_key(txin.amount, absolute[o]);
|
const crypto::public_key pkey = get_output_key(cur0, txin.amount, absolute[o]);
|
||||||
MINFO("Blackballing output " << pkey << ", due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings");
|
MINFO("Blackballing output " << pkey << ", due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings");
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
blackballs.push_back(pkey);
|
blackballs.push_back(pkey);
|
||||||
add_spent_output(txn, output_data(txin.amount, absolute[o]), true);
|
add_spent_output(txn, output_data(txin.amount, absolute[o]), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (get_relative_ring(txn, txin.k_image, relative_ring))
|
else if (n > 0 && get_relative_ring(txn, txin.k_image, relative_ring))
|
||||||
{
|
{
|
||||||
MINFO("Key image " << txin.k_image << " already seen: rings " <<
|
MDEBUG("Key image " << txin.k_image << " already seen: rings " <<
|
||||||
boost::join(relative_ring | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ") <<
|
boost::join(relative_ring | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " ") <<
|
||||||
", " << boost::join(txin.key_offsets | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
|
", " << boost::join(txin.key_offsets | boost::adaptors::transformed([](uint64_t out){return std::to_string(out);}), " "));
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
if (relative_ring != txin.key_offsets)
|
if (relative_ring != txin.key_offsets)
|
||||||
{
|
{
|
||||||
MINFO("Rings are different");
|
MDEBUG("Rings are different");
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
const std::vector<uint64_t> r0 = cryptonote::relative_output_offsets_to_absolute(relative_ring);
|
const std::vector<uint64_t> r0 = cryptonote::relative_output_offsets_to_absolute(relative_ring);
|
||||||
const std::vector<uint64_t> r1 = cryptonote::relative_output_offsets_to_absolute(txin.key_offsets);
|
const std::vector<uint64_t> r1 = cryptonote::relative_output_offsets_to_absolute(txin.key_offsets);
|
||||||
|
@ -886,7 +928,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
else if (common.size() == 1)
|
else if (common.size() == 1)
|
||||||
{
|
{
|
||||||
const crypto::public_key pkey = core_storage[n]->get_output_key(txin.amount, common[0]);
|
const crypto::public_key pkey = get_output_key(cur0, txin.amount, common[0]);
|
||||||
MINFO("Blackballing output " << pkey << ", due to being used in rings with a single common element");
|
MINFO("Blackballing output " << pkey << ", due to being used in rings with a single common element");
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
blackballs.push_back(pkey);
|
blackballs.push_back(pkey);
|
||||||
|
@ -894,7 +936,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MINFO("The intersection has more than one element, it's still ok");
|
MDEBUG("The intersection has more than one element, it's still ok");
|
||||||
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
|
||||||
for (const auto &out: r0)
|
for (const auto &out: r0)
|
||||||
if (std::find(common.begin(), common.end(), out) != common.end())
|
if (std::find(common.begin(), common.end(), out) != common.end())
|
||||||
|
@ -903,7 +945,8 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set_relative_ring(txn, txin.k_image, new_ring);
|
if (n == 0)
|
||||||
|
set_relative_ring(txn, txin.k_image, new_ring);
|
||||||
}
|
}
|
||||||
if (!blackballs.empty())
|
if (!blackballs.empty())
|
||||||
{
|
{
|
||||||
|
@ -976,7 +1019,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
if (known == absolute.size() - 1)
|
if (known == absolute.size() - 1)
|
||||||
{
|
{
|
||||||
const crypto::public_key pkey = core_storage[0]->get_output_key(od.amount, last_unknown);
|
const crypto::public_key pkey = get_output_key(cur0, od.amount, last_unknown);
|
||||||
MINFO("Blackballing output " << pkey << ", due to being used in a " <<
|
MINFO("Blackballing output " << pkey << ", due to being used in a " <<
|
||||||
absolute.size() << "-ring where all other outputs are known to be spent");
|
absolute.size() << "-ring where all other outputs are known to be spent");
|
||||||
blackballs.push_back(pkey);
|
blackballs.push_back(pkey);
|
||||||
|
@ -996,6 +1039,7 @@ int main(int argc, char* argv[])
|
||||||
uint64_t diff = get_num_spent_outputs(false) - start_blackballed_outputs;
|
uint64_t diff = get_num_spent_outputs(false) - start_blackballed_outputs;
|
||||||
LOG_PRINT_L0(std::to_string(diff) << " new outputs blackballed, " << get_num_spent_outputs(false) << " total outputs blackballed");
|
LOG_PRINT_L0(std::to_string(diff) << " new outputs blackballed, " << get_num_spent_outputs(false) << " total outputs blackballed");
|
||||||
LOG_PRINT_L0("Blockchain blackball data exported OK");
|
LOG_PRINT_L0("Blockchain blackball data exported OK");
|
||||||
|
close_db(env0, txn0, cur0, dbi0);
|
||||||
close();
|
close();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue