Skip to content

Commit 2ca0775

Browse files
jeffro256j-berman
andcommitted
carrot_impl: @j-berman dusty sweep review
Co-authored-by: j-berman <justinberman@protonmail.com>
1 parent 8ef8809 commit 2ca0775

File tree

3 files changed

+55
-9
lines changed

3 files changed

+55
-9
lines changed

src/carrot_impl/input_selection.inl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ std::pair<std::size_t, boost::multiprecision::uint128_t> get_input_count_for_max
6363

6464
std::size_t input_count = 0;
6565
boost::multiprecision::uint128_t cumulative_input_sum = 0;
66-
boost::multiprecision::uint128_t best_cumulative_input_sum = 0;
6766
std::size_t best_input_count = 0;
67+
boost::multiprecision::uint128_t best_cumulative_input_sum = 0;
68+
boost::multiprecision::uint128_t best_net_input_sum = 0;
6869
// for all valid input counts (or existing amount counts, whichever is fewer)...
6970
for (auto top_amount_it = top_amounts.crbegin(); top_amount_it != top_amounts.crend(); ++top_amount_it)
7071
{
@@ -82,12 +83,14 @@ std::pair<std::size_t, boost::multiprecision::uint128_t> get_input_count_for_max
8283
// if the input amount total is greater than fee for that number of inputs...
8384
if (cumulative_input_sum > current_fee)
8485
{
85-
// and if that input amount total is better than any other total observed yet...
86-
if (cumulative_input_sum > best_cumulative_input_sum)
86+
const boost::multiprecision::uint128_t net_input_sum = cumulative_input_sum - current_fee;
87+
// and if that input amount total minus its fees is better than any other total observed yet...
88+
if (net_input_sum > best_net_input_sum)
8789
{
8890
// set that as best.
89-
best_cumulative_input_sum = cumulative_input_sum;
9091
best_input_count = input_count;
92+
best_cumulative_input_sum = cumulative_input_sum;
93+
best_net_input_sum = net_input_sum;
9194
}
9295
}
9396
}

src/carrot_impl/multi_tx_proposal_utils.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ void make_multiple_carrot_transaction_proposals_sweep(
168168

169169
tx_proposals_out.reserve((selected_inputs.size() + FCMP_PLUS_PLUS_MAX_INPUTS - 1) / FCMP_PLUS_PLUS_MAX_INPUTS);
170170

171+
// callback for calling `get_input_count_for_max_usable_money()` on some slice of inputs starting at `window_offset`
171172
const auto get_input_count_for_max_usable_money_in_window =
172173
[&selected_inputs, &fee_by_input_count](const std::size_t window_offset)
173174
{
@@ -188,17 +189,24 @@ void make_multiple_carrot_transaction_proposals_sweep(
188189
fee_by_input_count).first;
189190
};
190191

192+
// To try to maximize the total amount of money sent in a sweep, we first order the amounts in
193+
// ascending order. Then from low to high, we slide a "window" over a slice of contiguous
194+
// amounts and call `get_input_count_for_max_usable_money_in_window` over that window. That call
195+
// will tell how many of the inputs in that window are dusty. If any are dusty, we should keep
196+
// sliding the window until we can't. Once that window stops, we use that window for the inputs
197+
// for the current transaction. Repeat until no inputs are left or only dusty inputs are left.
198+
191199
// while some selection of inputs of the highest amounts at some input count yields a net positive output sum...
192200
while (get_input_count_for_max_usable_money_in_window(0))
193201
{
194-
// slide a window in ascending amount order until some inputs in that window yield a net positive output sum..
195-
std::size_t window_offset = selected_inputs.size()
196-
- std::min<std::size_t>(CARROT_MAX_TX_INPUTS, selected_inputs.size());
202+
// slide a window in ascending amount order until all inputs in that window yield a net positive output sum...
203+
const std::size_t max_window_size = std::min<std::size_t>(CARROT_MAX_TX_INPUTS, selected_inputs.size());
204+
std::size_t window_offset = selected_inputs.size() - max_window_size;
197205
std::size_t n_tx_inputs = 0;
198206
do
199207
{
200208
n_tx_inputs = get_input_count_for_max_usable_money_in_window(window_offset);
201-
if (0 == window_offset || 0 != n_tx_inputs)
209+
if (0 == window_offset || max_window_size == n_tx_inputs)
202210
break;
203211
--window_offset;
204212
}

tests/unit_tests/carrot_impl.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,34 @@ TEST(carrot_impl, multi_account_transfer_over_transaction_16)
11771177
subtest_multi_account_transfer_over_transaction(tx_proposal);
11781178
}
11791179
//----------------------------------------------------------------------------------------------------------------------
1180+
TEST(carrot_impl, get_input_count_for_max_usable_money_1)
1181+
{
1182+
const std::vector<rct::xmr_amount> amounts{17, 7, 11, 8, 9};
1183+
1184+
const std::map<std::size_t, rct::xmr_amount> fee_by_input_count{
1185+
{1, 10},
1186+
{2, 20},
1187+
{3, 30},
1188+
{4, 40},
1189+
{5, 50},
1190+
{6, 60},
1191+
{7, 70},
1192+
{8, 80}
1193+
};
1194+
1195+
const auto input_count_for_max_usable_money = carrot::get_input_count_for_max_usable_money(
1196+
amounts.cbegin(),
1197+
amounts.cend(),
1198+
fee_by_input_count.size(),
1199+
fee_by_input_count);
1200+
1201+
const std::pair<std::size_t, boost::multiprecision::uint128_t> expected_input_count_for_max_usable_money{
1202+
2, 17 + 11
1203+
};
1204+
1205+
EXPECT_EQ(expected_input_count_for_max_usable_money, input_count_for_max_usable_money);
1206+
}
1207+
//----------------------------------------------------------------------------------------------------------------------
11801208
TEST(carrot_impl, make_single_transfer_input_selector_not_enough_money_1)
11811209
{
11821210
// no input candidates, should throw `not_enough_money`
@@ -1603,6 +1631,13 @@ TEST(carrot_impl, make_multiple_carrot_transaction_proposals_sweep_1)
16031631
ASSERT_EQ(1, tx_proposal.selfsend_payment_proposals.size());
16041632
ASSERT_TRUE(tx_proposal.extra.empty());
16051633

1634+
const carrot::CarrotPaymentProposalVerifiableSelfSendV1 &selfsend_payment_proposal
1635+
= tx_proposal.selfsend_payment_proposals.at(0);
1636+
ASSERT_EQ(0, selfsend_payment_proposal.proposal.amount);
1637+
ASSERT_EQ(0, selfsend_payment_proposal.subaddr_index.index.major);
1638+
ASSERT_EQ(0, selfsend_payment_proposal.subaddr_index.index.minor);
1639+
ASSERT_EQ(carrot::AddressDeriveType::Auto, selfsend_payment_proposal.subaddr_index.derive_type);
1640+
16061641
carrot::CarrotPaymentProposalV1 modified_normal_payment_proposal = normal_payment_proposal;
16071642
modified_normal_payment_proposal.amount = tx_proposal.normal_payment_proposals.at(0).amount;
16081643
ASSERT_EQ(modified_normal_payment_proposal, tx_proposal.normal_payment_proposals.at(0));
@@ -1622,4 +1657,4 @@ TEST(carrot_impl, make_multiple_carrot_transaction_proposals_sweep_1)
16221657
EXPECT_EQ(n_input_enote_amounts, seen_ota.size());
16231658
}
16241659
}
1625-
//----------------------------------------------------------------------------------------------------------------------
1660+
//----------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)