Adding Dandelion++ support to public networks:

- New flag in NOTIFY_NEW_TRANSACTION to indicate stem mode
  - Stem loops detected in tx_pool.cpp
  - Embargo timeout for a blackhole attack during stem phase
This commit is contained in:
Lee Clagett 2019-11-13 14:12:32 +00:00
parent 7c74e1919e
commit 02d887c2e5
25 changed files with 1562 additions and 171 deletions

View file

@ -926,29 +926,60 @@ namespace cryptonote
return 1;
}
std::vector<cryptonote::blobdata> newtxs;
newtxs.reserve(arg.txs.size());
for (size_t i = 0; i < arg.txs.size(); ++i)
relay_method tx_relay;
std::vector<blobdata> stem_txs{};
std::vector<blobdata> fluff_txs{};
if (arg.dandelionpp_fluff)
{
cryptonote::tx_verification_context tvc{};
m_core.handle_incoming_tx({arg.txs[i], crypto::null_hash}, tvc, relay_method::fluff, true);
if(tvc.m_verifivation_failed)
tx_relay = relay_method::fluff;
fluff_txs.reserve(arg.txs.size());
}
else
{
tx_relay = relay_method::stem;
stem_txs.reserve(arg.txs.size());
}
for (auto& tx : arg.txs)
{
tx_verification_context tvc{};
if (!m_core.handle_incoming_tx({tx, crypto::null_hash}, tvc, tx_relay, true))
{
LOG_PRINT_CCONTEXT_L1("Tx verification failed, dropping connection");
drop_connection(context, false, false);
return 1;
}
if(tvc.m_should_be_relayed)
newtxs.push_back(std::move(arg.txs[i]));
}
arg.txs = std::move(newtxs);
if(arg.txs.size())
switch (tvc.m_relay)
{
case relay_method::local:
case relay_method::stem:
stem_txs.push_back(std::move(tx));
break;
case relay_method::block:
case relay_method::fluff:
fluff_txs.push_back(std::move(tx));
break;
default:
case relay_method::none:
break;
}
}
if (!stem_txs.empty())
{
//TODO: add announce usage here
relay_transactions(arg, context.m_connection_id, context.m_remote_address.get_zone());
arg.dandelionpp_fluff = false;
arg.txs = std::move(stem_txs);
relay_transactions(arg, context.m_connection_id, context.m_remote_address.get_zone(), relay_method::stem);
}
if (!fluff_txs.empty())
{
//TODO: add announce usage here
arg.dandelionpp_fluff = true;
arg.txs = std::move(fluff_txs);
relay_transactions(arg, context.m_connection_id, context.m_remote_address.get_zone(), relay_method::fluff);
}
return 1;
}
//------------------------------------------------------------------------------------------------------------------------
@ -2387,14 +2418,14 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
bool t_cryptonote_protocol_handler<t_core>::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, const boost::uuids::uuid& source, epee::net_utils::zone zone)
bool t_cryptonote_protocol_handler<t_core>::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, const boost::uuids::uuid& source, epee::net_utils::zone zone, relay_method tx_relay)
{
/* Push all outgoing transactions to this function. The behavior needs to
identify how the transaction is going to be relayed, and then update the
local mempool before doing the relay. The code was already updating the
DB twice on received transactions - it is difficult to workaround this
due to the internal design. */
return m_p2p->send_txs(std::move(arg.txs), zone, source, m_core) != epee::net_utils::zone::invalid;
return m_p2p->send_txs(std::move(arg.txs), zone, source, m_core, tx_relay) != epee::net_utils::zone::invalid;
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>