aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-11-02 22:27:25 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-11-06 15:47:05 +0000
commit3dba7f252e080ca9ce9c86dca033e6b0b00ee21d (patch)
treee1e87e8fef2305e063a73bc228296e6f613f7739 /src
parentMerge pull request #4676 (diff)
downloadmonero-3dba7f252e080ca9ce9c86dca033e6b0b00ee21d.tar.xz
protocol: option to pad transaction relay to the next kB
To help protect one's privacy from traffic volume analysis for people using Tor or I2P. This will really fly once we relay txes on a timer rather than on demand, though. Off by default for now since it's wasteful and doesn't bring anything until I2P's in.
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp10
-rw-r--r--src/cryptonote_core/cryptonote_core.h8
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_defs.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl31
4 files changed, 50 insertions, 1 deletions
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index d8c38bf9e..c55499365 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -163,6 +163,11 @@ namespace cryptonote
, "Relay blocks as normal blocks"
, false
};
+ static const command_line::arg_descriptor<bool> arg_pad_transactions = {
+ "pad-transactions"
+ , "Pad relayed transactions to help defend against traffic volume analysis"
+ , false
+ };
static const command_line::arg_descriptor<size_t> arg_max_txpool_weight = {
"max-txpool-weight"
, "Set maximum txpool weight in bytes."
@@ -188,7 +193,8 @@ namespace cryptonote
m_disable_dns_checkpoints(false),
m_update_download(0),
m_nettype(UNDEFINED),
- m_update_available(false)
+ m_update_available(false),
+ m_pad_transactions(false)
{
m_checkpoints_updating.clear();
set_cryptonote_protocol(pprotocol);
@@ -282,6 +288,7 @@ namespace cryptonote
command_line::add_arg(desc, arg_offline);
command_line::add_arg(desc, arg_disable_dns_checkpoints);
command_line::add_arg(desc, arg_max_txpool_weight);
+ command_line::add_arg(desc, arg_pad_transactions);
command_line::add_arg(desc, arg_block_notify);
miner::init_options(desc);
@@ -320,6 +327,7 @@ namespace cryptonote
set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints));
test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height));
m_fluffy_blocks_enabled = !get_arg(vm, arg_no_fluffy_blocks);
+ m_pad_transactions = get_arg(vm, arg_pad_transactions);
m_offline = get_arg(vm, arg_offline);
m_disable_dns_checkpoints = get_arg(vm, arg_disable_dns_checkpoints);
if (!command_line::is_arg_defaulted(vm, arg_fluffy_blocks))
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 80c452f53..cef42d207 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -757,6 +757,13 @@ namespace cryptonote
bool fluffy_blocks_enabled() const { return m_fluffy_blocks_enabled; }
/**
+ * @brief get whether transaction relay should be padded
+ *
+ * @return whether transaction relay should be padded
+ */
+ bool pad_transactions() const { return m_pad_transactions; }
+
+ /**
* @brief check a set of hashes against the precompiled hash set
*
* @return number of usable blocks
@@ -1014,6 +1021,7 @@ namespace cryptonote
bool m_fluffy_blocks_enabled;
bool m_offline;
+ bool m_pad_transactions;
};
}
diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h
index db159f0f4..d5bb50930 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_defs.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h
@@ -146,9 +146,11 @@ namespace cryptonote
struct request
{
std::vector<blobdata> txs;
+ std::string _; // padding
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(txs)
+ KV_SERIALIZE(_)
END_KV_SERIALIZE_MAP()
};
};
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index c2c660e8c..6efdcc25e 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -1724,8 +1724,39 @@ skip:
bool t_cryptonote_protocol_handler<t_core>::relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, cryptonote_connection_context& exclude_context)
{
// no check for success, so tell core they're relayed unconditionally
+ const bool pad_transactions = m_core.pad_transactions();
+ size_t bytes = pad_transactions ? 9 /* header */ + 4 /* 1 + 'txs' */ + tools::get_varint_data(arg.txs.size()).size() : 0;
for(auto tx_blob_it = arg.txs.begin(); tx_blob_it!=arg.txs.end(); ++tx_blob_it)
+ {
m_core.on_transaction_relayed(*tx_blob_it);
+ if (pad_transactions)
+ bytes += tools::get_varint_data(tx_blob_it->size()).size() + tx_blob_it->size();
+ }
+
+ if (pad_transactions)
+ {
+ // stuff some dummy bytes in to stay safe from traffic volume analysis
+ static constexpr size_t granularity = 1024;
+ size_t padding = granularity - bytes % granularity;
+ const size_t overhead = 2 /* 1 + '_' */ + tools::get_varint_data(padding).size();
+ if (overhead > padding)
+ padding = 0;
+ else
+ padding -= overhead;
+ arg._ = std::string(padding, ' ');
+
+ std::string arg_buff;
+ epee::serialization::store_t_to_binary(arg, arg_buff);
+
+ // we probably lowballed the payload size a bit, so added a but too much. Fix this now.
+ size_t remove = arg_buff.size() % granularity;
+ if (remove > arg._.size())
+ arg._.clear();
+ else
+ arg._.resize(arg._.size() - remove);
+ // if the size of _ moved enough, we might lose byte in size encoding, we don't care
+ }
+
return relay_post_notify<NOTIFY_NEW_TRANSACTIONS>(arg, exclude_context);
}
//------------------------------------------------------------------------------------------------------------------------