Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump ring size to 16 for v15 #8178

Merged
merged 1 commit into from
Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/cryptonote_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
#define HF_VERSION_MIN_MIXIN_4 6
#define HF_VERSION_MIN_MIXIN_6 7
#define HF_VERSION_MIN_MIXIN_10 8
#define HF_VERSION_MIN_MIXIN_15 15
#define HF_VERSION_ENFORCE_RCT 6
#define HF_VERSION_PER_BYTE_FEE 8
#define HF_VERSION_SMALLER_BP 10
Expand Down
24 changes: 15 additions & 9 deletions src/cryptonote_core/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3309,7 +3309,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
size_t n_unmixable = 0, n_mixable = 0;
size_t min_actual_mixin = std::numeric_limits<size_t>::max();
size_t max_actual_mixin = 0;
const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_10 ? 10 : hf_version >= HF_VERSION_MIN_MIXIN_6 ? 6 : hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 2;
const size_t min_mixin = hf_version >= HF_VERSION_MIN_MIXIN_15 ? 15 : hf_version >= HF_VERSION_MIN_MIXIN_10 ? 10 : hf_version >= HF_VERSION_MIN_MIXIN_6 ? 6 : hf_version >= HF_VERSION_MIN_MIXIN_4 ? 4 : 2;
for (const auto& txin : tx.vin)
{
// non txin_to_key inputs will be rejected below
Expand Down Expand Up @@ -3352,14 +3352,11 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
}
}

if (((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && min_actual_mixin != 10) || (hf_version >= HF_VERSION_MIN_MIXIN_10+2 && min_actual_mixin > 10))
{
MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (min_actual_mixin + 1) << "), it should be 11");
tvc.m_low_mixin = true;
return false;
}

if (min_actual_mixin < min_mixin)
// The only circumstance where ring sizes less than expected are
// allowed is when spending unmixable non-RCT outputs in the chain.
// Caveat: at HF_VERSION_MIN_MIXIN_15, temporarily allow ring sizes
// of 11 to allow a grace period in the transition to larger ring size.
if (min_actual_mixin < min_mixin && !(hf_version == HF_VERSION_MIN_MIXIN_15 && min_actual_mixin == 10))
{
if (n_unmixable == 0)
{
Expand All @@ -3373,6 +3370,15 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
tvc.m_low_mixin = true;
return false;
}
} else if ((hf_version > HF_VERSION_MIN_MIXIN_15 && min_actual_mixin > 15)
|| (hf_version == HF_VERSION_MIN_MIXIN_15 && min_actual_mixin != 15 && min_actual_mixin != 10) // grace period to allow either 15 or 10
|| (hf_version < HF_VERSION_MIN_MIXIN_15 && hf_version >= HF_VERSION_MIN_MIXIN_10+2 && min_actual_mixin > 10)
|| ((hf_version == HF_VERSION_MIN_MIXIN_10 || hf_version == HF_VERSION_MIN_MIXIN_10+1) && min_actual_mixin != 10)
)
{
MERROR_VER("Tx " << get_transaction_hash(tx) << " has invalid ring size (" << (min_actual_mixin + 1) << "), it should be " << (min_mixin + 1));
tvc.m_low_mixin = true;
return false;
}

// min/max tx version based on HF, and we accept v1 txes if having a non mixable
Expand Down
69 changes: 5 additions & 64 deletions src/simplewallet/simplewallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ typedef cryptonote::simple_wallet sw;

#define EXTENDED_LOGS_FILE "wallet_details.log"

#define DEFAULT_MIX 10

#define MIN_RING_SIZE 11 // Used to inform user about min ring size -- does not track actual protocol

#define OLD_AGE_WARN_THRESHOLD (30 * 86400 / DIFFICULTY_TARGET_V2) // 30 days

#define LOCK_IDLE_SCOPE() \
Expand Down Expand Up @@ -2472,59 +2468,6 @@ bool simple_wallet::set_store_tx_info(const std::vector<std::string> &args/* = s
return true;
}

bool simple_wallet::set_default_ring_size(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
if (m_wallet->watch_only())
{
fail_msg_writer() << tr("wallet is watch-only and cannot transfer");
return true;
}
try
{
if (strchr(args[1].c_str(), '-'))
{
fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE;
return true;
}
uint32_t ring_size = boost::lexical_cast<uint32_t>(args[1]);
if (ring_size < MIN_RING_SIZE && ring_size != 0)
{
fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE;
return true;
}

if (ring_size != 0 && ring_size != DEFAULT_MIX+1)
{
if (m_wallet->use_fork_rules(8, 0))
{
message_writer() << tr("WARNING: from v8, ring size will be fixed and this setting will be ignored.");
}
else
{
message_writer() << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended.");
}
}

const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
m_wallet->default_mixin(ring_size > 0 ? ring_size - 1 : 0);
m_wallet->rewrite(m_wallet_file, pwd_container->password());
}
return true;
}
catch(const boost::bad_lexical_cast &)
{
fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE;
return true;
}
catch(...)
{
fail_msg_writer() << tr("could not change default ring size");
return true;
}
}

bool simple_wallet::set_default_priority(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
uint32_t priority = 0;
Expand Down Expand Up @@ -3386,8 +3329,6 @@ simple_wallet::simple_wallet()
" Whether to print detailed information about ring members during confirmation.\n "
"store-tx-info <1|0>\n "
" Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n "
"default-ring-size <n>\n "
" Set the default ring size (obsolete).\n "
"auto-refresh <1|0>\n "
" Whether to automatically synchronize new blocks from the daemon.\n "
"refresh-type <full|optimize-coinbase|no-coinbase|default>\n "
Expand Down Expand Up @@ -3896,7 +3837,6 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("always-confirm-transfers", set_always_confirm_transfers, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("print-ring-members", set_print_ring_members, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("store-tx-info", set_store_tx_info, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("default-ring-size", set_default_ring_size, tr("integer >= ") << MIN_RING_SIZE);
CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)"));
CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4, or one of ") << join_priority_strings(", "));
Expand Down Expand Up @@ -6539,7 +6479,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri

priority = m_wallet->adjust_priority(priority);

size_t fake_outs_count = DEFAULT_MIX;
const size_t min_ring_size = m_wallet->get_min_ring_size();
size_t fake_outs_count = min_ring_size - 1;
if(local_args.size() > 0) {
size_t ring_size;
if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0]))
Expand Down Expand Up @@ -6862,7 +6803,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
if (vin.type() == typeid(txin_to_key))
{
const txin_to_key& in_to_key = boost::get<txin_to_key>(vin);
if (in_to_key.key_offsets.size() != DEFAULT_MIX + 1)
if (in_to_key.key_offsets.size() != min_ring_size)
default_ring_size = false;
}
}
Expand Down Expand Up @@ -7140,7 +7081,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co

priority = m_wallet->adjust_priority(priority);

size_t fake_outs_count = DEFAULT_MIX;
size_t fake_outs_count = m_wallet->get_min_ring_size() - 1;
if(local_args.size() > 0) {
size_t ring_size;
if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0]))
Expand Down Expand Up @@ -7417,7 +7358,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)

priority = m_wallet->adjust_priority(priority);

size_t fake_outs_count = DEFAULT_MIX;
size_t fake_outs_count = m_wallet->get_min_ring_size() - 1;
if(local_args.size() > 0) {
size_t ring_size;
if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0]))
Expand Down
1 change: 0 additions & 1 deletion src/simplewallet/simplewallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ namespace cryptonote
bool set_always_confirm_transfers(const std::vector<std::string> &args = std::vector<std::string>());
bool set_print_ring_members(const std::vector<std::string> &args = std::vector<std::string>());
bool set_store_tx_info(const std::vector<std::string> &args = std::vector<std::string>());
bool set_default_ring_size(const std::vector<std::string> &args = std::vector<std::string>());
bool set_auto_refresh(const std::vector<std::string> &args = std::vector<std::string>());
bool set_refresh_type(const std::vector<std::string> &args = std::vector<std::string>());
bool set_confirm_missing_payment_id(const std::vector<std::string> &args = std::vector<std::string>());
Expand Down
4 changes: 4 additions & 0 deletions src/wallet/wallet2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7380,6 +7380,8 @@ int wallet2::get_fee_algorithm()
//------------------------------------------------------------------------------------------------------------------------------
uint64_t wallet2::get_min_ring_size()
{
if (use_fork_rules(HF_VERSION_MIN_MIXIN_15, 0))
return 16;
if (use_fork_rules(8, 10))
return 11;
if (use_fork_rules(7, 10))
Expand All @@ -7393,6 +7395,8 @@ uint64_t wallet2::get_min_ring_size()
//------------------------------------------------------------------------------------------------------------------------------
uint64_t wallet2::get_max_ring_size()
{
if (use_fork_rules(HF_VERSION_MIN_MIXIN_15, 0))
return 16;
if (use_fork_rules(8, 10))
return 11;
return 0;
Expand Down
4 changes: 2 additions & 2 deletions tests/functional_tests/cold_signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def transfer(self):
res = self.cold_wallet.export_key_images(True)
self.hot_wallet.import_key_images(res.signed_key_images, offset = res.offset)

res = self.hot_wallet.transfer([dst], ring_size = 11, get_tx_key = False)
res = self.hot_wallet.transfer([dst], ring_size = 16, get_tx_key = False)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 0
Expand All @@ -121,7 +121,7 @@ def transfer(self):
desc = res.desc[0]
assert desc.amount_in >= amount + fee
assert desc.amount_out == desc.amount_in - fee
assert desc.ring_size == 11
assert desc.ring_size == 16
assert desc.unlock_time == 0
assert desc.payment_id in ['', '0000000000000000']
assert desc.change_amount == desc.amount_in - 1000000000000 - fee
Expand Down
2 changes: 1 addition & 1 deletion tests/functional_tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace
const command_line::arg_descriptor<std::string> arg_daemon_addr_b = {"daemon-addr-b", "", "127.0.0.1:8082"};

const command_line::arg_descriptor<uint64_t> arg_transfer_amount = {"transfer_amount", "", 60000000000000};
const command_line::arg_descriptor<size_t> arg_mix_in_factor = {"mix-in-factor", "", 10};
const command_line::arg_descriptor<size_t> arg_mix_in_factor = {"mix-in-factor", "", 15};
const command_line::arg_descriptor<size_t> arg_tx_count = {"tx-count", "", 100};
const command_line::arg_descriptor<size_t> arg_tx_per_second = {"tx-per-second", "", 20};
const command_line::arg_descriptor<size_t> arg_test_repeat_count = {"test_repeat_count", "", 1};
Expand Down
4 changes: 2 additions & 2 deletions tests/functional_tests/multisig.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def run_test(self):
self.mine('41mro238grj56GnrWkakAKTkBy2yDcXYsUZ2iXCM9pe5Ueajd2RRc6Fhh3uBXT2UAKhAsUJ7Fg5zjjF2U1iGciFk5ief4ZP', 5)
self.mine('44vZSprQKJQRFe6t1VHgU4ESvq2dv7TjBLVGE7QscKxMdFSiyyPCEV64NnKUQssFPyWxc2meyt7j63F2S2qtCTRL6dakeff', 5)
self.mine('47puypSwsV1gvUDratmX4y58fSwikXVehEiBhVLxJA1gRCxHyrRgTDr4NnKUQssFPyWxc2meyt7j63F2S2qtCTRL6aRPj5U', 5)
self.mine('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 60)
self.mine('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80)

self.test_states()

Expand Down Expand Up @@ -261,7 +261,7 @@ def transfer(self, signers):
desc = res.desc[0]
assert desc.amount_in >= amount + fee
assert desc.amount_out == desc.amount_in - fee
assert desc.ring_size == 11
assert desc.ring_size == 16
assert desc.unlock_time == 0
assert not 'payment_id' in desc or desc.payment_id in ['', '0000000000000000']
assert desc.change_amount == desc.amount_in - 1000000000000 - fee
Expand Down
16 changes: 8 additions & 8 deletions tests/functional_tests/transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ def mine(self):
res = daemon.get_info()
height = res.height

daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80)
daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 100)
for i in range(len(self.wallet)):
self.wallet[i].refresh()
res = self.wallet[i].get_height()
assert res.height == height + 80
assert res.height == height + 100

def transfer(self):
daemon = Daemon()
Expand All @@ -110,23 +110,23 @@ def transfer(self):

print ('Checking short payment IDs cannot be used when not in an integrated address')
ok = False
try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = '1234567812345678', get_tx_key = False)
try: self.wallet[0].transfer([dst], ring_size = 16, payment_id = '1234567812345678', get_tx_key = False)
except: ok = True
assert ok

print ('Checking long payment IDs are rejected')
ok = False
try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False, get_tx_hex = True)
try: self.wallet[0].transfer([dst], ring_size = 16, payment_id = payment_id, get_tx_key = False, get_tx_hex = True)
except: ok = True
assert ok

print ('Checking empty destination is rejected')
ok = False
try: self.wallet[0].transfer([], ring_size = 11, get_tx_key = False)
try: self.wallet[0].transfer([], ring_size = 16, get_tx_key = False)
except: ok = True
assert ok

res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = False, get_tx_hex = True)
res = self.wallet[0].transfer([dst], ring_size = 16, get_tx_key = False, get_tx_hex = True)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 0
Expand Down Expand Up @@ -231,7 +231,7 @@ def transfer(self):
print("Creating transfer to another, manual relay")

dst = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1000000000000}
res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = True, do_not_relay = True, get_tx_hex = True)
res = self.wallet[0].transfer([dst], ring_size = 16, get_tx_key = True, do_not_relay = True, get_tx_hex = True)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 32*2
Expand Down Expand Up @@ -321,7 +321,7 @@ def transfer(self):
dst0 = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000}
dst1 = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1100000000000}
dst2 = {'address': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 'amount': 1200000000000}
res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 11, get_tx_key = True)
res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 16, get_tx_key = True)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 32*2
Expand Down