remove obsolete daemon selection of fake outs and old tx construction

This commit is contained in:
moneromooo-monero 2018-08-13 16:18:32 +00:00
parent e8049be955
commit be001326d1
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
16 changed files with 18 additions and 955 deletions

View file

@ -1717,17 +1717,6 @@ size_t Blockchain::get_alternative_blocks_count() const
//------------------------------------------------------------------
// This function adds the output specified by <amount, i> to the result_outs container
// unlocked and other such checks should be done by here.
void Blockchain::add_out_to_get_random_outs(COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs, uint64_t amount, size_t i) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oen = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry());
oen.global_amount_index = i;
output_data_t data = m_db->get_output_key(amount, i);
oen.out_key = data.pubkey;
}
uint64_t Blockchain::get_num_mature_outputs(uint64_t amount) const
{
uint64_t num_outs = m_db->get_num_outputs(amount);
@ -1745,243 +1734,12 @@ uint64_t Blockchain::get_num_mature_outputs(uint64_t amount) const
return num_outs;
}
std::vector<uint64_t> Blockchain::get_random_outputs(uint64_t amount, uint64_t count) const
{
uint64_t num_outs = get_num_mature_outputs(amount);
std::vector<uint64_t> indices;
std::unordered_set<uint64_t> seen_indices;
// if there aren't enough outputs to mix with (or just enough),
// use all of them. Eventually this should become impossible.
if (num_outs <= count)
{
for (uint64_t i = 0; i < num_outs; i++)
{
// get tx_hash, tx_out_index from DB
tx_out_index toi = m_db->get_output_tx_and_index(amount, i);
// if tx is unlocked, add output to indices
if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
{
indices.push_back(i);
}
}
}
else
{
// while we still need more mixins
while (indices.size() < count)
{
// if we've gone through every possible output, we've gotten all we can
if (seen_indices.size() == num_outs)
{
break;
}
// get a random output index from the DB. If we've already seen it,
// return to the top of the loop and try again, otherwise add it to the
// list of output indices we've seen.
// triangular distribution over [a,b) with a=0, mode c=b=up_index_limit
uint64_t r = crypto::rand<uint64_t>() % ((uint64_t)1 << 53);
double frac = std::sqrt((double)r / ((uint64_t)1 << 53));
uint64_t i = (uint64_t)(frac*num_outs);
// just in case rounding up to 1 occurs after sqrt
if (i == num_outs)
--i;
if (seen_indices.count(i))
{
continue;
}
seen_indices.emplace(i);
// get tx_hash, tx_out_index from DB
tx_out_index toi = m_db->get_output_tx_and_index(amount, i);
// if the output's transaction is unlocked, add the output's index to
// our list.
if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
{
indices.push_back(i);
}
}
}
return indices;
}
crypto::public_key Blockchain::get_output_key(uint64_t amount, uint64_t global_index) const
{
output_data_t data = m_db->get_output_key(amount, global_index);
return data.pubkey;
}
//------------------------------------------------------------------
// This function takes an RPC request for mixins and creates an RPC response
// with the requested mixins.
// TODO: figure out why this returns boolean / if we should be returning false
// in some cases
bool Blockchain::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
// for each amount that we need to get mixins for, get <n> random outputs
// from BlockchainDB where <n> is req.outs_count (number of mixins).
for (uint64_t amount : req.amounts)
{
// create outs_for_amount struct and populate amount field
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount& result_outs = *res.outs.insert(res.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::outs_for_amount());
result_outs.amount = amount;
std::vector<uint64_t> indices = get_random_outputs(amount, req.outs_count);
for (auto i : indices)
{
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry& oe = *result_outs.outs.insert(result_outs.outs.end(), COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry());
oe.global_amount_index = i;
oe.out_key = get_output_key(amount, i);
}
}
return true;
}
//------------------------------------------------------------------
// This function adds the ringct output at index i to the list
// unlocked and other such checks should be done by here.
void Blockchain::add_out_to_get_rct_random_outs(std::list<COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::out_entry>& outs, uint64_t amount, size_t i) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::out_entry& oen = *outs.insert(outs.end(), COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::out_entry());
oen.amount = amount;
oen.global_amount_index = i;
output_data_t data = m_db->get_output_key(amount, i);
oen.out_key = data.pubkey;
oen.commitment = data.commitment;
}
//------------------------------------------------------------------
// This function takes an RPC request for mixins and creates an RPC response
// with the requested mixins.
// TODO: figure out why this returns boolean / if we should be returning false
// in some cases
bool Blockchain::get_random_rct_outs(const COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::request& req, COMMAND_RPC_GET_RANDOM_RCT_OUTPUTS::response& res) const
{
LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock);
// for each amount that we need to get mixins for, get <n> random outputs
// from BlockchainDB where <n> is req.outs_count (number of mixins).
auto num_outs = m_db->get_num_outputs(0);
// ensure we don't include outputs that aren't yet eligible to be used
// outpouts are sorted by height
while (num_outs > 0)
{
const tx_out_index toi = m_db->get_output_tx_and_index(0, num_outs - 1);
const uint64_t height = m_db->get_tx_block_height(toi.first);
if (height + CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE <= m_db->height())
break;
--num_outs;
}
std::unordered_set<uint64_t> seen_indices;
// if there aren't enough outputs to mix with (or just enough),
// use all of them. Eventually this should become impossible.
if (num_outs <= req.outs_count)
{
for (uint64_t i = 0; i < num_outs; i++)
{
// get tx_hash, tx_out_index from DB
tx_out_index toi = m_db->get_output_tx_and_index(0, i);
// if tx is unlocked, add output to result_outs
if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
{
add_out_to_get_rct_random_outs(res.outs, 0, i);
}
}
}
else
{
// while we still need more mixins
while (res.outs.size() < req.outs_count)
{
// if we've gone through every possible output, we've gotten all we can
if (seen_indices.size() == num_outs)
{
break;
}
// get a random output index from the DB. If we've already seen it,
// return to the top of the loop and try again, otherwise add it to the
// list of output indices we've seen.
// triangular distribution over [a,b) with a=0, mode c=b=up_index_limit
uint64_t r = crypto::rand<uint64_t>() % ((uint64_t)1 << 53);
double frac = std::sqrt((double)r / ((uint64_t)1 << 53));
uint64_t i = (uint64_t)(frac*num_outs);
// just in case rounding up to 1 occurs after sqrt
if (i == num_outs)
--i;
if (seen_indices.count(i))
{
continue;
}
seen_indices.emplace(i);
// get tx_hash, tx_out_index from DB
tx_out_index toi = m_db->get_output_tx_and_index(0, i);
// if the output's transaction is unlocked, add the output's index to
// our list.
if (is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first)))
{
add_out_to_get_rct_random_outs(res.outs, 0, i);
}
}
}
if (res.outs.size() < req.outs_count)
return false;
#if 0
// if we do not have enough RCT inputs, we can pick from the non RCT ones
// which will have a zero mask
if (res.outs.size() < req.outs_count)
{
LOG_PRINT_L0("Out of RCT inputs (" << res.outs.size() << "/" << req.outs_count << "), using regular ones");
// TODO: arbitrary selection, needs better
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request req2 = AUTO_VAL_INIT(req2);
COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response res2 = AUTO_VAL_INIT(res2);
req2.outs_count = req.outs_count - res.outs.size();
static const uint64_t amounts[] = {1, 10, 20, 50, 100, 200, 500, 1000, 10000};
for (uint64_t a: amounts)
req2.amounts.push_back(a);
if (!get_random_outs_for_amounts(req2, res2))
return false;
// pick random ones from there
while (res.outs.size() < req.outs_count)
{
int list_idx = rand() % (sizeof(amounts)/sizeof(amounts[0]));
if (!res2.outs[list_idx].outs.empty())
{
const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::out_entry oe = res2.outs[list_idx].outs.back();
res2.outs[list_idx].outs.pop_back();
add_out_to_get_rct_random_outs(res.outs, res2.outs[list_idx].amount, oe.global_amount_index);
}
}
}
#endif
return true;
}
//------------------------------------------------------------------
bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMAND_RPC_GET_OUTPUTS_BIN::response& res) const
{