carrot_impl: correct subaddr account index for change
This commit is contained in:
@@ -358,6 +358,7 @@ TEST(carrot_fcmp, receive_scan_spend_and_verify_serialized_carrot_tx)
|
||||
}
|
||||
},
|
||||
alice.carrot_account_spend_pubkey,
|
||||
{{0, 0}, AddressDeriveType::Carrot},
|
||||
{},
|
||||
{},
|
||||
tx_proposal);
|
||||
|
||||
@@ -159,6 +159,7 @@ static void subtest_multi_account_transfer_over_transaction(const unittest_trans
|
||||
tx_preproposal.extra_extra,
|
||||
make_fake_input_selection_callback(),
|
||||
ss_keys.carrot_account_spend_pubkey,
|
||||
{{0, 0}, AddressDeriveType::Carrot},
|
||||
{},
|
||||
{},
|
||||
tx_proposal);
|
||||
|
||||
@@ -103,6 +103,17 @@ CarrotDestinationV1 mock_carrot_and_legacy_keys::subaddress(const subaddress_ind
|
||||
return addr;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> mock_carrot_and_legacy_keys::subaddress_map_cn() const
|
||||
{
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> res;
|
||||
for (const auto &p : subaddress_map)
|
||||
if (p.second.derive_type == AddressDeriveType::PreCarrot)
|
||||
res.emplace(p.first, cryptonote::subaddress_index{p.second.index.major, p.second.index.minor});
|
||||
CHECK_AND_ASSERT_THROW_MES(!res.empty(),
|
||||
"mock_carrot_and_legacy_keys::subaddress_map_cn: subaddress map does not contain pre-carrot subaddresses");
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void mock_carrot_and_legacy_keys::opening_for_subaddress(const subaddress_index_extended &subaddress_index,
|
||||
crypto::secret_key &address_privkey_g_out,
|
||||
crypto::secret_key &address_privkey_t_out,
|
||||
@@ -506,12 +517,20 @@ CarrotDestinationV1 convert_destination_v1(const cryptonote::tx_destination_entr
|
||||
};
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotPaymentProposalV1 convert_normal_payment_proposal_v1(const cryptonote::tx_destination_entry &cn_dst)
|
||||
cryptonote::tx_destination_entry convert_destination_v1(const CarrotDestinationV1 &dst, const rct::xmr_amount amount)
|
||||
{
|
||||
return cryptonote::tx_destination_entry(amount,
|
||||
{dst.address_spend_pubkey, dst.address_view_pubkey},
|
||||
dst.is_subaddress);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotPaymentProposalV1 convert_normal_payment_proposal_v1(const cryptonote::tx_destination_entry &cn_dst,
|
||||
const janus_anchor_t randomness)
|
||||
{
|
||||
return CarrotPaymentProposalV1{
|
||||
.destination = convert_destination_v1(cn_dst),
|
||||
.amount = cn_dst.amount,
|
||||
.randomness = gen_janus_anchor()
|
||||
.randomness = randomness
|
||||
};
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -94,6 +94,8 @@ struct mock_carrot_and_legacy_keys
|
||||
|
||||
CarrotDestinationV1 subaddress(const subaddress_index_extended &subaddress_index) const;
|
||||
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddress_map_cn() const;
|
||||
|
||||
// brief: opening_for_subaddress - return (k^g_a, k^t_a) for j s.t. K^j_s = (k^g_a * G + k^t_a * T)
|
||||
void opening_for_subaddress(const subaddress_index_extended &subaddress_index,
|
||||
crypto::secret_key &address_privkey_g_out,
|
||||
@@ -177,7 +179,10 @@ std::uint64_t gen_block_index();
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotDestinationV1 convert_destination_v1(const cryptonote::tx_destination_entry &cn_dst);
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotPaymentProposalV1 convert_normal_payment_proposal_v1(const cryptonote::tx_destination_entry &cn_dst);
|
||||
cryptonote::tx_destination_entry convert_destination_v1(const CarrotDestinationV1 &dst, const rct::xmr_amount amount);
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotPaymentProposalV1 convert_normal_payment_proposal_v1(const cryptonote::tx_destination_entry &cn_dst,
|
||||
const janus_anchor_t randomness = gen_janus_anchor());
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotPaymentProposalSelfSendV1 convert_selfsend_payment_proposal_v1(const cryptonote::tx_destination_entry &cn_dst);
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -427,6 +427,7 @@ cryptonote::transaction construct_carrot_pruned_transaction_fake_inputs(
|
||||
/*extra=*/{},
|
||||
std::move(select_inputs),
|
||||
acc_keys.m_account_address.m_spend_public_key,
|
||||
{{0, 0}, carrot::AddressDeriveType::PreCarrot},
|
||||
{},
|
||||
{},
|
||||
tx_proposal);
|
||||
|
||||
@@ -49,7 +49,7 @@ static tools::wallet2::transfer_details gen_transfer_details()
|
||||
.m_spent_height = 0,
|
||||
.m_key_image = crypto::key_image{rct::rct2pk(rct::pkGen())},
|
||||
.m_mask = rct::skGen(),
|
||||
.m_amount = crypto::rand_range<rct::xmr_amount>(0, COIN), // [0, 1] XMR i.e. [0, 1e12] pXMR
|
||||
.m_amount = crypto::rand_range<rct::xmr_amount>(COIN, 2 * COIN), // [1, 2] XMR i.e. [1e12, 2e12] pXMR
|
||||
.m_rct = true,
|
||||
.m_key_image_known = true,
|
||||
.m_key_image_request = false,
|
||||
@@ -158,7 +158,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_transfer_1)
|
||||
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_transfer(
|
||||
transfers,
|
||||
/*subaddress_map=*/{},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
dsts,
|
||||
/*fee_per_weight=*/1,
|
||||
/*extra=*/{},
|
||||
@@ -188,6 +188,97 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_transfer_1)
|
||||
transfers.front().amount());
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_transfer_2)
|
||||
{
|
||||
carrot::mock::mock_carrot_and_legacy_keys alice;
|
||||
alice.generate();
|
||||
carrot::mock::mock_carrot_and_legacy_keys bob;
|
||||
bob.generate();
|
||||
|
||||
static constexpr uint32_t spending_subaddr_account = 2;
|
||||
static_assert(spending_subaddr_account);
|
||||
|
||||
tools::wallet2::transfer_container transfers;
|
||||
std::uint64_t top_block_index = 0;
|
||||
std::unordered_map<crypto::key_image, std::size_t> allowed_transfers;
|
||||
for (size_t i = 0; i < FCMP_PLUS_PLUS_MAX_INPUTS + 2; ++i)
|
||||
{
|
||||
tools::wallet2::transfer_details &td = tools::add_element(transfers);
|
||||
td = gen_transfer_details();
|
||||
td.m_subaddr_index.major = (i % 2 == 0) ? spending_subaddr_account : (spending_subaddr_account - 1);
|
||||
td.m_subaddr_index.minor = crypto::rand_range<std::uint32_t>(0, carrot::mock::MAX_SUBADDRESS_MINOR_INDEX);
|
||||
top_block_index = std::max(top_block_index, td.m_block_height);
|
||||
|
||||
if (td.m_subaddr_index.major == spending_subaddr_account)
|
||||
allowed_transfers.emplace(td.m_key_image, i);
|
||||
}
|
||||
top_block_index += CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE;
|
||||
|
||||
const rct::xmr_amount out_amount = COIN * 3 / 4;
|
||||
|
||||
const std::vector<cryptonote::tx_destination_entry> dsts{
|
||||
carrot::mock::convert_destination_v1(bob.cryptonote_address(), out_amount)
|
||||
};
|
||||
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_transfer(
|
||||
transfers,
|
||||
alice.subaddress_map_cn(),
|
||||
dsts,
|
||||
/*fee_per_weight=*/1,
|
||||
/*extra=*/{},
|
||||
/*subaddr_account=*/spending_subaddr_account,
|
||||
/*subaddr_indices=*/{},
|
||||
/*ignore_above=*/MONEY_SUPPLY,
|
||||
/*ignore_below=*/0,
|
||||
{},
|
||||
top_block_index,
|
||||
alice.legacy_acb.get_keys());
|
||||
|
||||
ASSERT_EQ(1, tx_proposals.size());
|
||||
const carrot::CarrotTransactionProposalV1 &tx_proposal = tx_proposals.at(0);
|
||||
|
||||
// Assert basic length facts about tx proposal
|
||||
ASSERT_LE(tx_proposal.key_images_sorted.size(), 2);
|
||||
ASSERT_EQ(1, tx_proposal.normal_payment_proposals.size());
|
||||
ASSERT_EQ(1, tx_proposal.selfsend_payment_proposals.size());
|
||||
EXPECT_EQ(0, tx_proposal.extra.size());
|
||||
|
||||
const carrot::CarrotPaymentProposalV1 &normal_payment_proposal = tx_proposal.normal_payment_proposals.at(0);
|
||||
const carrot::CarrotPaymentProposalVerifiableSelfSendV1 &selfsend_payment_proposal = tx_proposal.selfsend_payment_proposals.at(0);
|
||||
|
||||
// Assert that selected transfers have spending_subaddr_account subaddr major index
|
||||
boost::multiprecision::uint128_t in_sum = 0;
|
||||
for (std::size_t in_idx = 0; in_idx < tx_proposal.key_images_sorted.size(); ++in_idx)
|
||||
{
|
||||
const crypto::key_image &ki = tx_proposal.key_images_sorted.at(in_idx);
|
||||
if (in_idx > 0)
|
||||
{
|
||||
ASSERT_LT(ki, tx_proposal.key_images_sorted.at(in_idx - 1));
|
||||
}
|
||||
ASSERT_EQ(1, allowed_transfers.count(ki));
|
||||
const tools::wallet2::transfer_details &td = transfers.at(allowed_transfers.at(ki));
|
||||
ASSERT_EQ(spending_subaddr_account, td.m_subaddr_index.major);
|
||||
in_sum += td.amount();
|
||||
}
|
||||
|
||||
// Assert balanced amounts
|
||||
boost::multiprecision::uint128_t out_sum = tx_proposal.fee;
|
||||
out_sum += normal_payment_proposal.amount;
|
||||
out_sum += selfsend_payment_proposal.proposal.amount;
|
||||
ASSERT_EQ(in_sum, out_sum);
|
||||
|
||||
// Assert pubkeys/subaddr indices/amounts of payment proposals
|
||||
EXPECT_EQ(carrot::mock::convert_normal_payment_proposal_v1(dsts.at(0), normal_payment_proposal.randomness), normal_payment_proposal);
|
||||
EXPECT_NE(normal_payment_proposal.randomness, carrot::janus_anchor_t{});
|
||||
EXPECT_EQ(spending_subaddr_account, selfsend_payment_proposal.subaddr_index.index.major);
|
||||
EXPECT_EQ(0, selfsend_payment_proposal.subaddr_index.index.minor);
|
||||
EXPECT_EQ(alice.subaddress({{spending_subaddr_account, 0}, carrot::AddressDeriveType::PreCarrot}).address_spend_pubkey,
|
||||
selfsend_payment_proposal.proposal.destination_address_spend_pubkey);
|
||||
EXPECT_EQ(carrot::CarrotEnoteType::CHANGE, selfsend_payment_proposal.proposal.enote_type);
|
||||
EXPECT_FALSE(selfsend_payment_proposal.proposal.internal_message);
|
||||
EXPECT_FALSE(selfsend_payment_proposal.proposal.enote_ephemeral_pubkey);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_1)
|
||||
{
|
||||
cryptonote::account_base alice;
|
||||
@@ -199,7 +290,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_1)
|
||||
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(
|
||||
transfers,
|
||||
/*subaddress_map=*/{},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
{transfers.front().m_key_image},
|
||||
bob.get_keys().m_account_address,
|
||||
/*is_subaddress=*/false,
|
||||
@@ -234,7 +325,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_2)
|
||||
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(
|
||||
transfers,
|
||||
/*subaddress_map=*/{},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
{transfers.front().m_key_image},
|
||||
bob.get_keys().m_account_address,
|
||||
/*is_subaddress=*/false,
|
||||
@@ -277,7 +368,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_3)
|
||||
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(
|
||||
transfers,
|
||||
/*subaddress_map=*/{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
{transfers.front().m_key_image},
|
||||
alice.get_keys().m_account_address,
|
||||
/*is_subaddress=*/false,
|
||||
@@ -353,7 +444,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_4)
|
||||
// make tx proposals
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(
|
||||
transfers,
|
||||
/*subaddress_map=*/{},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
selected_key_images,
|
||||
bob.get_keys().m_account_address,
|
||||
/*is_subaddress=*/false,
|
||||
@@ -436,7 +527,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_5)
|
||||
// make tx proposals
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(
|
||||
transfers,
|
||||
/*subaddress_map=*/{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
selected_key_images,
|
||||
alice.get_keys().m_account_address,
|
||||
/*is_subaddress=*/false,
|
||||
@@ -519,7 +610,7 @@ TEST(wallet_tx_builder, make_carrot_transaction_proposals_wallet2_sweep_6)
|
||||
// make tx proposals
|
||||
const std::vector<carrot::CarrotTransactionProposalV1> tx_proposals = tools::wallet::make_carrot_transaction_proposals_wallet2_sweep(
|
||||
transfers,
|
||||
/*subaddress_map=*/{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
{{alice.get_keys().m_account_address.m_spend_public_key, {}}},
|
||||
selected_key_images,
|
||||
alice.get_keys().m_account_address,
|
||||
/*is_subaddress=*/false,
|
||||
|
||||
Reference in New Issue
Block a user