remove output blackballing

This commit is contained in:
tobtoht 2023-03-02 15:25:49 +01:00
parent 94e67bf96b
commit bda5a597d9
No known key found for this signature in database
GPG Key ID: E45B10DD027D2472
12 changed files with 3 additions and 2257 deletions

View File

@ -57,19 +57,6 @@ monero_private_headers(blockchain_export
${blockchain_export_private_headers})
set(blockchain_blackball_sources
blockchain_blackball.cpp
)
set(blockchain_blackball_private_headers
bootstrap_file.h
blocksdat_file.h
bootstrap_serialization.h
)
monero_private_headers(blockchain_blackball
${blockchain_blackball_private_headers})
set(blockchain_usage_sources
blockchain_usage.cpp
)
@ -181,29 +168,6 @@ set_property(TARGET blockchain_export
OUTPUT_NAME "monero-blockchain-export")
install(TARGETS blockchain_export DESTINATION bin)
monero_add_executable(blockchain_blackball
${blockchain_blackball_sources}
${blockchain_blackball_private_headers})
target_link_libraries(blockchain_blackball
PRIVATE
wallet
cryptonote_core
blockchain_db
version
epee
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${EXTRA_LIBRARIES})
set_property(TARGET blockchain_blackball
PROPERTY
OUTPUT_NAME "monero-blockchain-mark-spent-outputs")
install(TARGETS blockchain_blackball DESTINATION bin)
monero_add_executable(blockchain_usage
${blockchain_usage_sources}
${blockchain_usage_private_headers})

File diff suppressed because it is too large Load Diff

View File

@ -265,9 +265,6 @@ namespace
const char* USAGE_SET_RING("set_ring <filename> | ( <key_image> absolute|relative <index> [<index>...] )");
const char* USAGE_UNSET_RING("unset_ring <txid> | ( <key_image> [<key_image>...] )");
const char* USAGE_SAVE_KNOWN_RINGS("save_known_rings");
const char* USAGE_MARK_OUTPUT_SPENT("mark_output_spent <amount>/<offset> | <filename> [add]");
const char* USAGE_MARK_OUTPUT_UNSPENT("mark_output_unspent <amount>/<offset>");
const char* USAGE_IS_OUTPUT_SPENT("is_output_spent <amount>/<offset>");
const char* USAGE_FREEZE("freeze <key_image>");
const char* USAGE_THAW("thaw <key_image>");
const char* USAGE_FROZEN("frozen <key_image>");
@ -1912,152 +1909,6 @@ bool simple_wallet::unset_ring(const std::vector<std::string> &args)
return true;
}
bool simple_wallet::blackball(const std::vector<std::string> &args)
{
uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets;
if (args.size() == 0)
{
PRINT_USAGE(USAGE_MARK_OUTPUT_SPENT);
return true;
}
try
{
if (sscanf(args[0].c_str(), "%" PRIu64 "/%" PRIu64, &amount, &offset) == 2)
{
m_wallet->blackball_output(std::make_pair(amount, offset));
}
else if (epee::file_io_utils::is_file_exist(args[0]))
{
std::vector<std::pair<uint64_t, uint64_t>> outputs;
char str[256];
std::unique_ptr<FILE, tools::close_file> f(fopen(args[0].c_str(), "r"));
if (f)
{
while (!feof(f.get()))
{
if (!fgets(str, sizeof(str), f.get()))
break;
const size_t len = strlen(str);
if (len > 0 && str[len - 1] == '\n')
str[len - 1] = 0;
if (!str[0])
continue;
if (sscanf(str, "@%" PRIu64, &amount) == 1)
{
continue;
}
if (amount == std::numeric_limits<uint64_t>::max())
{
fail_msg_writer() << tr("First line is not an amount");
return true;
}
if (sscanf(str, "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets <= std::numeric_limits<uint64_t>::max() - offset)
{
while (num_offsets--)
outputs.push_back(std::make_pair(amount, offset++));
}
else if (sscanf(str, "%" PRIu64, &offset) == 1)
{
outputs.push_back(std::make_pair(amount, offset));
}
else
{
fail_msg_writer() << tr("Invalid output: ") << str;
return true;
}
}
f.reset();
bool add = false;
if (args.size() > 1)
{
if (args[1] != "add")
{
fail_msg_writer() << tr("Bad argument: ") + args[1] + ": " + tr("should be \"add\"");
return true;
}
add = true;
}
m_wallet->set_blackballed_outputs(outputs, add);
}
else
{
fail_msg_writer() << tr("Failed to open file");
return true;
}
}
else
{
fail_msg_writer() << tr("Invalid output key, and file doesn't exist");
return true;
}
}
catch (const std::exception &e)
{
fail_msg_writer() << tr("Failed to mark output spent: ") << e.what();
}
return true;
}
bool simple_wallet::unblackball(const std::vector<std::string> &args)
{
std::pair<uint64_t, uint64_t> output;
if (args.size() != 1)
{
PRINT_USAGE(USAGE_MARK_OUTPUT_UNSPENT);
return true;
}
if (sscanf(args[0].c_str(), "%" PRIu64 "/%" PRIu64, &output.first, &output.second) != 2)
{
fail_msg_writer() << tr("Invalid output");
return true;
}
try
{
m_wallet->unblackball_output(output);
}
catch (const std::exception &e)
{
fail_msg_writer() << tr("Failed to mark output unspent: ") << e.what();
}
return true;
}
bool simple_wallet::blackballed(const std::vector<std::string> &args)
{
std::pair<uint64_t, uint64_t> output;
if (args.size() != 1)
{
PRINT_USAGE(USAGE_IS_OUTPUT_SPENT);
return true;
}
if (sscanf(args[0].c_str(), "%" PRIu64 "/%" PRIu64, &output.first, &output.second) != 2)
{
fail_msg_writer() << tr("Invalid output");
return true;
}
try
{
if (m_wallet->is_output_blackballed(output))
message_writer() << tr("Spent: ") << output.first << "/" << output.second;
else
message_writer() << tr("Not spent: ") << output.first << "/" << output.second;
}
catch (const std::exception &e)
{
fail_msg_writer() << tr("Failed to check whether output is spent: ") << e.what();
}
return true;
}
bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
{
try
@ -3499,18 +3350,6 @@ simple_wallet::simple_wallet()
boost::bind(&simple_wallet::on_command, this, &simple_wallet::save_known_rings, _1),
tr(USAGE_SAVE_KNOWN_RINGS),
tr("Save known rings to the shared rings database"));
m_cmd_binder.set_handler("mark_output_spent",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::blackball, _1),
tr(USAGE_MARK_OUTPUT_SPENT),
tr("Mark output(s) as spent so they never get selected as fake outputs in a ring"));
m_cmd_binder.set_handler("mark_output_unspent",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::unblackball, _1),
tr(USAGE_MARK_OUTPUT_UNSPENT),
tr("Marks an output as unspent so it may get selected as a fake output in a ring"));
m_cmd_binder.set_handler("is_output_spent",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::blackballed, _1),
tr(USAGE_IS_OUTPUT_SPENT),
tr("Checks whether an output is marked as spent"));
m_cmd_binder.set_handler("freeze",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::freeze, _1),
tr(USAGE_FREEZE),

View File

@ -248,9 +248,6 @@ namespace cryptonote
bool set_ring(const std::vector<std::string>& args);
bool unset_ring(const std::vector<std::string>& args);
bool save_known_rings(const std::vector<std::string>& args);
bool blackball(const std::vector<std::string>& args);
bool unblackball(const std::vector<std::string>& args);
bool blackballed(const std::vector<std::string>& args);
bool freeze(const std::vector<std::string>& args);
bool thaw(const std::vector<std::string>& args);
bool frozen(const std::vector<std::string>& args);

View File

@ -2365,88 +2365,6 @@ bool WalletImpl::useForkRules(uint8_t version, int64_t early_blocks) const
return m_wallet->use_fork_rules(version,early_blocks);
}
bool WalletImpl::blackballOutputs(const std::vector<std::string> &outputs, bool add)
{
std::vector<std::pair<uint64_t, uint64_t>> raw_outputs;
raw_outputs.reserve(outputs.size());
uint64_t amount = std::numeric_limits<uint64_t>::max(), offset, num_offsets;
for (const std::string &str: outputs)
{
if (sscanf(str.c_str(), "@%" PRIu64, &amount) == 1)
continue;
if (amount == std::numeric_limits<uint64_t>::max())
{
setStatusError("First line is not an amount");
return true;
}
if (sscanf(str.c_str(), "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets <= std::numeric_limits<uint64_t>::max() - offset)
{
while (num_offsets--)
raw_outputs.push_back(std::make_pair(amount, offset++));
}
else if (sscanf(str.c_str(), "%" PRIu64, &offset) == 1)
{
raw_outputs.push_back(std::make_pair(amount, offset));
}
else
{
setStatusError(tr("Invalid output: ") + str);
return false;
}
}
bool ret = m_wallet->set_blackballed_outputs(raw_outputs, add);
if (!ret)
{
setStatusError(tr("Failed to mark outputs as spent"));
return false;
}
return true;
}
bool WalletImpl::blackballOutput(const std::string &amount, const std::string &offset)
{
uint64_t raw_amount, raw_offset;
if (!epee::string_tools::get_xtype_from_string(raw_amount, amount))
{
setStatusError(tr("Failed to parse output amount"));
return false;
}
if (!epee::string_tools::get_xtype_from_string(raw_offset, offset))
{
setStatusError(tr("Failed to parse output offset"));
return false;
}
bool ret = m_wallet->blackball_output(std::make_pair(raw_amount, raw_offset));
if (!ret)
{
setStatusError(tr("Failed to mark output as spent"));
return false;
}
return true;
}
bool WalletImpl::unblackballOutput(const std::string &amount, const std::string &offset)
{
uint64_t raw_amount, raw_offset;
if (!epee::string_tools::get_xtype_from_string(raw_amount, amount))
{
setStatusError(tr("Failed to parse output amount"));
return false;
}
if (!epee::string_tools::get_xtype_from_string(raw_offset, offset))
{
setStatusError(tr("Failed to parse output offset"));
return false;
}
bool ret = m_wallet->unblackball_output(std::make_pair(raw_amount, raw_offset));
if (!ret)
{
setStatusError(tr("Failed to mark output as unspent"));
return false;
}
return true;
}
bool WalletImpl::getRing(const std::string &key_image, std::vector<uint64_t> &ring) const
{
crypto::key_image raw_key_image;

View File

@ -208,9 +208,6 @@ public:
virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) override;
virtual std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const override;
virtual std::string getDefaultDataDir() const override;
virtual bool blackballOutputs(const std::vector<std::string> &outputs, bool add) override;
virtual bool blackballOutput(const std::string &amount, const std::string &offset) override;
virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override;
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const override;
virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const override;
virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative) override;

View File

@ -1038,15 +1038,6 @@ struct Wallet
*/
virtual void setOffline(bool offline) = 0;
virtual bool isOffline() const = 0;
//! blackballs a set of outputs
virtual bool blackballOutputs(const std::vector<std::string> &outputs, bool add) = 0;
//! blackballs an output
virtual bool blackballOutput(const std::string &amount, const std::string &offset) = 0;
//! unblackballs an output
virtual bool unblackballOutput(const std::string &amount, const std::string &offset) = 0;
//! gets the ring used for a key image, if any
virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const = 0;

View File

@ -57,13 +57,6 @@ static int compare_hash32(const MDB_val *a, const MDB_val *b)
return 0;
}
static 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 std::string compress_ring(const std::vector<uint64_t> &ring, uint64_t tag)
{
std::string s;
@ -201,8 +194,6 @@ static size_t get_ring_data_size(size_t n_entries)
return n_entries * (32 + 1024); // highball 1kB for the ring data to make sure
}
enum { BLACKBALL_BLACKBALL, BLACKBALL_UNBLACKBALL, BLACKBALL_QUERY, BLACKBALL_CLEAR};
namespace tools
{
@ -234,10 +225,6 @@ ringdb::ringdb(std::string filename, const std::string &genesis):
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
mdb_set_compare(txn, dbi_rings, compare_hash32);
dbr = mdb_dbi_open(txn, ("blackballs2-" + genesis).c_str(), MDB_CREATE | MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED, &dbi_blackballs);
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to open LMDB dbi: " + std::string(mdb_strerror(dbr)));
mdb_set_dupsort(txn, dbi_blackballs, compare_uint64);
dbr = mdb_txn_commit(txn);
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn creating/opening database: " + std::string(mdb_strerror(dbr)));
tx_active = false;
@ -253,7 +240,6 @@ void ringdb::close()
if (env)
{
mdb_dbi_close(env, dbi_rings);
mdb_dbi_close(env, dbi_blackballs);
mdb_env_close(env);
env = NULL;
}
@ -439,103 +425,4 @@ bool ringdb::set_ring(const crypto::chacha_key &chacha_key, const crypto::key_im
return set_rings(chacha_key, rings, relative);
}
bool ringdb::blackball_worker(const std::vector<std::pair<uint64_t, uint64_t>> &outputs, int op)
{
MDB_txn *txn;
MDB_cursor *cursor;
int dbr;
bool tx_active = false;
bool ret = true;
THROW_WALLET_EXCEPTION_IF(outputs.size() > 1 && op == BLACKBALL_QUERY, tools::error::wallet_internal_error, "Blackball query only makes sense for a single output");
dbr = resize_env(env, filename.c_str(), 32 * 2 * outputs.size()); // a pubkey, and some slack
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to set env map size: " + std::string(mdb_strerror(dbr)));
dbr = mdb_txn_begin(env, NULL, 0, &txn);
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_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_cursor_open(txn, dbi_blackballs, &cursor);
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to create cursor for blackballs table: " + std::string(mdb_strerror(dbr)));
MDB_val key, data;
for (const std::pair<uint64_t, uint64_t> &output: outputs)
{
key.mv_data = (void*)&output.first;
key.mv_size = sizeof(output.first);
data.mv_data = (void*)&output.second;
data.mv_size = sizeof(output.second);
switch (op)
{
case BLACKBALL_BLACKBALL:
MDEBUG("Marking output " << output.first << "/" << output.second << " as spent");
dbr = mdb_cursor_put(cursor, &key, &data, MDB_NODUPDATA);
if (dbr == MDB_KEYEXIST)
dbr = 0;
break;
case BLACKBALL_UNBLACKBALL:
MDEBUG("Marking output " << output.first << "/" << output.second << " as unspent");
dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH);
if (dbr == 0)
dbr = mdb_cursor_del(cursor, 0);
break;
case BLACKBALL_QUERY:
dbr = mdb_cursor_get(cursor, &key, &data, MDB_GET_BOTH);
THROW_WALLET_EXCEPTION_IF(dbr && dbr != MDB_NOTFOUND, tools::error::wallet_internal_error, "Failed to lookup in blackballs table: " + std::string(mdb_strerror(dbr)));
ret = dbr != MDB_NOTFOUND;
if (dbr == MDB_NOTFOUND)
dbr = 0;
break;
case BLACKBALL_CLEAR:
break;
default:
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, "Invalid blackball op");
}
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to query blackballs table: " + std::string(mdb_strerror(dbr)));
}
mdb_cursor_close(cursor);
if (op == BLACKBALL_CLEAR)
{
dbr = mdb_drop(txn, dbi_blackballs, 0);
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to clear blackballs table: " + std::string(mdb_strerror(dbr)));
}
dbr = mdb_txn_commit(txn);
THROW_WALLET_EXCEPTION_IF(dbr, tools::error::wallet_internal_error, "Failed to commit txn blackballing output to database: " + std::string(mdb_strerror(dbr)));
tx_active = false;
return ret;
}
bool ringdb::blackball(const std::vector<std::pair<uint64_t, uint64_t>> &outputs)
{
return blackball_worker(outputs, BLACKBALL_BLACKBALL);
}
bool ringdb::blackball(const std::pair<uint64_t, uint64_t> &output)
{
std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
return blackball_worker(outputs, BLACKBALL_BLACKBALL);
}
bool ringdb::unblackball(const std::pair<uint64_t, uint64_t> &output)
{
std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
return blackball_worker(outputs, BLACKBALL_UNBLACKBALL);
}
bool ringdb::blackballed(const std::pair<uint64_t, uint64_t> &output)
{
std::vector<std::pair<uint64_t, uint64_t>> outputs(1, output);
return blackball_worker(outputs, BLACKBALL_QUERY);
}
bool ringdb::clear_blackballs()
{
return blackball_worker(std::vector<std::pair<uint64_t, uint64_t>>(), BLACKBALL_CLEAR);
}
}

View File

@ -53,19 +53,9 @@ namespace tools
bool set_ring(const crypto::chacha_key &chacha_key, const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative);
bool set_rings(const crypto::chacha_key &chacha_key, const std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &rings, bool relative);
bool blackball(const std::pair<uint64_t, uint64_t> &output);
bool blackball(const std::vector<std::pair<uint64_t, uint64_t>> &outputs);
bool unblackball(const std::pair<uint64_t, uint64_t> &output);
bool blackballed(const std::pair<uint64_t, uint64_t> &output);
bool clear_blackballs();
private:
bool blackball_worker(const std::vector<std::pair<uint64_t, uint64_t>> &outputs, int op);
private:
std::string filename;
MDB_env *env;
MDB_dbi dbi_rings;
MDB_dbi dbi_blackballs;
};
}

View File

@ -8016,45 +8016,6 @@ bool wallet2::find_and_save_rings(bool force)
return true;
}
bool wallet2::blackball_output(const std::pair<uint64_t, uint64_t> &output)
{
if (!m_ringdb)
return false;
try { return m_ringdb->blackball(output); }
catch (const std::exception &e) { return false; }
}
bool wallet2::set_blackballed_outputs(const std::vector<std::pair<uint64_t, uint64_t>> &outputs, bool add)
{
if (!m_ringdb)
return false;
try
{
bool ret = true;
if (!add)
ret &= m_ringdb->clear_blackballs();
ret &= m_ringdb->blackball(outputs);
return ret;
}
catch (const std::exception &e) { return false; }
}
bool wallet2::unblackball_output(const std::pair<uint64_t, uint64_t> &output)
{
if (!m_ringdb)
return false;
try { return m_ringdb->unblackball(output); }
catch (const std::exception &e) { return false; }
}
bool wallet2::is_output_blackballed(const std::pair<uint64_t, uint64_t> &output) const
{
if (!m_ringdb)
return false;
try { return m_ringdb->blackballed(output); }
catch (const std::exception &e) { return false; }
}
bool wallet2::lock_keys_file()
{
if (m_wallet_file.empty())
@ -8111,8 +8072,6 @@ bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_out
return false;
}
valid_public_keys_cache.insert(rct::rct2pk(mask));
// if (is_output_blackballed(output_public_key)) // don't add blackballed outputs
// return false;
outs.back().push_back(item);
return true;
}
@ -8477,24 +8436,13 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
std::unordered_map<const char*, std::set<uint64_t>> picks;
// while we still need more mixins
uint64_t num_usable_outs = num_outs;
bool allow_blackballed = false;
MDEBUG("Starting gamma picking with " << num_outs << ", num_usable_outs " << num_usable_outs
MDEBUG("Starting gamma picking with " << num_outs
<< ", requested_outputs_count " << requested_outputs_count);
while (num_found < requested_outputs_count)
{
// if we've gone through every possible output, we've gotten all we can
if (seen_indices.size() == num_usable_outs)
{
// there is a first pass which rejects blackballed outputs, then a second pass
// which allows them if we don't have enough non blackballed outputs to reach
// the required amount of outputs (since consensus does not care about blackballed
// outputs, we still need to reach the minimum ring size)
if (allow_blackballed)
break;
MINFO("Not enough output not marked as spent, we'll allow outputs marked as spent");
allow_blackballed = true;
num_usable_outs = num_outs;
if (seen_indices.size() == num_outs) {
break;
}
// get a random output index from the DB. If we've already seen it,
@ -8570,11 +8518,6 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
if (seen_indices.count(i))
continue;
if (!allow_blackballed && is_output_blackballed(std::make_pair(amount, i))) // don't add blackballed outputs
{
--num_usable_outs;
continue;
}
seen_indices.emplace(i);
picks[type].insert(i);

View File

@ -1580,11 +1580,6 @@ private:
bool unset_ring(const crypto::hash &txid);
bool find_and_save_rings(bool force = true);
bool blackball_output(const std::pair<uint64_t, uint64_t> &output);
bool set_blackballed_outputs(const std::vector<std::pair<uint64_t, uint64_t>> &outputs, bool add = false);
bool unblackball_output(const std::pair<uint64_t, uint64_t> &output);
bool is_output_blackballed(const std::pair<uint64_t, uint64_t> &output) const;
void freeze(size_t idx);
void thaw(size_t idx);
bool frozen(size_t idx) const;

View File

@ -60,23 +60,13 @@ static crypto::key_image generate_key_image()
return key_image;
}
static std::pair<uint64_t, uint64_t> generate_output()
{
return std::make_pair(rand(), rand());
}
static crypto::chacha_key get_KEY_1() { static const crypto::chacha_key KEY_1 = generate_chacha_key(); return KEY_1; }
static crypto::chacha_key get_KEY_2() { static const crypto::chacha_key KEY_2 = generate_chacha_key(); return KEY_2; }
static crypto::key_image get_KEY_IMAGE_1() { static const crypto::key_image KEY_IMAGE_1 = generate_key_image(); return KEY_IMAGE_1; }
static std::pair<uint64_t, uint64_t> get_OUTPUT_1() { static const std::pair<uint64_t, uint64_t> OUTPUT_1 = generate_output(); return OUTPUT_1; }
static std::pair<uint64_t, uint64_t> get_OUTPUT_2() { static const std::pair<uint64_t, uint64_t> OUTPUT_2 = generate_output(); return OUTPUT_2; }
#define KEY_1 get_KEY_1()
#define KEY_2 get_KEY_2()
#define KEY_IMAGE_1 get_KEY_IMAGE_1()
#define OUTPUT_1 get_OUTPUT_1()
#define OUTPUT_2 get_OUTPUT_2()
class RingDB: public tools::ringdb
{
@ -142,58 +132,3 @@ TEST(ringdb, different_genesis)
ASSERT_TRUE(ringdb.set_ring(KEY_1, KEY_IMAGE_1, outs, false));
ASSERT_FALSE(ringdb.get_ring(KEY_2, KEY_IMAGE_1, outs2));
}
TEST(spent_outputs, not_found)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
ASSERT_FALSE(ringdb.blackballed(OUTPUT_2));
}
TEST(spent_outputs, found)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
ASSERT_TRUE(ringdb.blackballed(OUTPUT_1));
}
TEST(spent_outputs, vector)
{
RingDB ringdb;
std::vector<std::pair<uint64_t, uint64_t>> outputs;
outputs.push_back(std::make_pair(0, 1));
outputs.push_back(std::make_pair(10, 3));
outputs.push_back(std::make_pair(10, 4));
outputs.push_back(std::make_pair(10, 8));
outputs.push_back(std::make_pair(20, 0));
outputs.push_back(std::make_pair(20, 1));
outputs.push_back(std::make_pair(30, 5));
ASSERT_TRUE(ringdb.blackball(outputs));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(0, 1)));
ASSERT_FALSE(ringdb.blackballed(std::make_pair(10, 2)));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(10, 3)));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(10, 4)));
ASSERT_FALSE(ringdb.blackballed(std::make_pair(10, 5)));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(10, 8)));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(20, 0)));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(20, 1)));
ASSERT_FALSE(ringdb.blackballed(std::make_pair(20, 2)));
ASSERT_TRUE(ringdb.blackballed(std::make_pair(30, 5)));
}
TEST(spent_outputs, mark_as_unspent)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
ASSERT_TRUE(ringdb.unblackball(OUTPUT_1));
ASSERT_FALSE(ringdb.blackballed(OUTPUT_1));
}
TEST(spent_outputs, clear)
{
RingDB ringdb;
ASSERT_TRUE(ringdb.blackball(OUTPUT_1));
ASSERT_TRUE(ringdb.clear_blackballs());
ASSERT_FALSE(ringdb.blackballed(OUTPUT_1));
}