make scanning pre-carrot and carrot coinbase txs work

This commit is contained in:
akildemir
2025-05-14 16:02:35 +03:00
parent 87be655738
commit 18ec1c331b
11 changed files with 41 additions and 5 deletions

View File

@@ -61,6 +61,8 @@ struct CarrotEnoteV1 final
crypto::public_key onetime_address;
/// C_a
rct::key amount_commitment;
/// asset type
std::string asset_type;
/// a_enc
encrypted_amount_t amount_enc;
/// anchor_enc
@@ -92,6 +94,8 @@ struct CarrotCoinbaseEnoteV1 final
crypto::public_key onetime_address;
/// a
rct::xmr_amount amount;
/// asset type
std::string asset_type;
/// anchor_enc
encrypted_janus_anchor_t anchor_enc;
/// view_tag

View File

@@ -282,8 +282,9 @@ void get_coinbase_output_proposal_v1(const CarrotPaymentProposalV1 &proposal,
s_sender_receiver,
output_enote_out.onetime_address);
// 6. save the amount and block index
// 6. save the amount and block index and asset type
output_enote_out.amount = proposal.amount;
output_enote_out.asset_type = proposal.asset_type;
output_enote_out.block_index = block_index;
}
//-------------------------------------------------------------------------------------------------------------------

View File

@@ -59,6 +59,8 @@ struct CarrotPaymentProposalV1 final
CarrotDestinationV1 destination;
/// b
rct::xmr_amount amount;
/// asset type
std::string asset_type;
/// anchor_norm: secret 16-byte randomness for Janus anchor
janus_anchor_t randomness;
};

View File

@@ -360,6 +360,7 @@ cryptonote::transaction store_carrot_to_coinbase_transaction_v1(
const std::uint64_t block_index = enotes.at(0).block_index;
cryptonote::transaction tx;
tx.type = cryptonote::transaction_type::MINER;
tx.pruned = false;
tx.version = 2;
tx.unlock_time = block_index + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
@@ -379,6 +380,7 @@ cryptonote::transaction store_carrot_to_coinbase_transaction_v1(
cryptonote::txout_to_carrot_v1{
.key = enote.onetime_address,
.view_tag = enote.view_tag,
.asset_type = enote.asset_type,
.encrypted_janus_anchor = enote.anchor_enc
}
});
@@ -411,6 +413,7 @@ cryptonote::transaction make_single_enote_carrot_coinbase_transaction_v1(const C
const CarrotPaymentProposalV1 payment_proposal{
.destination = destination,
.amount = block_reward,
.asset_type = "SAL1",
.randomness = gen_janus_anchor()
};
@@ -443,6 +446,9 @@ bool try_load_carrot_coinbase_enote_from_transaction_v1(const cryptonote::transa
const cryptonote::txout_to_carrot_v1 * const c = boost::strict_get<cryptonote::txout_to_carrot_v1>(&o.target);
CHECK_AND_ASSERT_MES(c, false, "try_load_carrot_coinbase_enote_from_transaction_v1: wrong output type");
// asset type
enote_out.asset_type = c->asset_type;
//K_o
enote_out.onetime_address = c->key;

View File

@@ -1308,6 +1308,8 @@ namespace cryptonote
output_asset_type = boost::get< txout_to_key>(out.target).asset_type;
else if (out.target.type() == typeid(txout_to_tagged_key))
output_asset_type = boost::get< txout_to_tagged_key >(out.target).asset_type;
else if (out.target.type() == typeid(txout_to_carrot_v1))
output_asset_type = boost::get<txout_to_carrot_v1>(out.target).asset_type;
else
{
LOG_ERROR("Unexpected output target type found: " << out.target.type().name() << " - cannot retrieve output_asset_type");
@@ -1325,6 +1327,8 @@ namespace cryptonote
output_unlock_time = boost::get< txout_to_key>(out.target).unlock_time;
else if (out.target.type() == typeid(txout_to_tagged_key))
output_unlock_time = boost::get< txout_to_tagged_key >(out.target).unlock_time;
else if (out.target.type() == typeid(txout_to_carrot_v1))
output_unlock_time = boost::get<txout_to_carrot_v1>(out.target).unlock_time;
else
{
LOG_ERROR("Unexpected output target type found: " << out.target.type().name() << " - cannot retrieve output_unlock_time");
@@ -1375,7 +1379,7 @@ namespace cryptonote
{
if (hf_version >= HF_VERSION_CARROT)
{
// from v18, require outputs be carrot outputs
// from v11, require outputs be carrot outputs
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx));
} else {

View File

@@ -1370,7 +1370,7 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height,
CHECK_AND_ASSERT_MES(check_output_types(b.miner_tx, hf_version), false, "miner transaction has invalid output type(s) in block " << get_block_hash(b));
// from carrot or v18, require output pubkeys be sorted in strictly increasing lexicographical order
// from carrot or v11, require output pubkeys be sorted in strictly increasing lexicographical order
const bool tx_is_carrot = !b.miner_tx.vout.empty() && b.miner_tx.vout.at(0).target.type() == typeid(txout_to_carrot_v1);
const bool should_enforce_sorted_outputs = hf_version > HF_VERSION_CARROT || tx_is_carrot;
if (should_enforce_sorted_outputs) {
@@ -1504,6 +1504,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
case HF_VERSION_AUDIT2:
case HF_VERSION_AUDIT2_PAUSE:
case HF_VERSION_TREASURY_SAL1_MINT:
case HF_VERSION_CARROT:
if (b.miner_tx.amount_burnt > 0) {
CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt");
money_in_use += b.miner_tx.amount_burnt;
@@ -3698,7 +3699,7 @@ bool Blockchain::check_tx_type_and_version(const transaction& tx, tx_verificatio
return false;
}
// from carrot or v18, require output pubkeys be sorted in strictly increasing lexicographical order
// from carrot or v11, require output pubkeys be sorted in strictly increasing lexicographical order
const bool tx_is_carrot = !tx.vout.empty() && tx.vout.at(0).target.type() == typeid(txout_to_carrot_v1);
const bool should_enforce_sorted_outputs = hf_version > HF_VERSION_CARROT || tx_is_carrot;
if (should_enforce_sorted_outputs) {

View File

@@ -450,7 +450,9 @@ namespace cryptonote
miner_address.m_view_public_key,
destination);
tx = carrot::make_single_enote_carrot_coinbase_transaction_v1(destination, block_reward, height, extra_nonce);
uint64_t stake_reward = block_reward / 5;
tx = carrot::make_single_enote_carrot_coinbase_transaction_v1(destination, block_reward - stake_reward, height, extra_nonce);
tx.amount_burnt = stake_reward;
tx.invalidate_hashes();
}
catch (const std::exception &e)

View File

@@ -92,6 +92,9 @@ const hardfork_t testnet_hard_forks[] = {
// version 10 treasury mint starts from block 1100
{10, 1100, 0, 1739780005 },
// version 11 carrot starts from block 1500
{11, 1500, 0, 1739780010 },
};
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);

View File

@@ -102,6 +102,9 @@ static bool try_load_pre_carrot_enote(const bool is_coinbase,
CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(o, enote_out.onetime_address),
false,
"make_pre_carrot_enote: missing output public key");
CHECK_AND_ASSERT_MES(cryptonote::get_output_asset_type(o, enote_out.asset_type),
false,
"make_pre_carrot_enote: missing output asset type");
enote_out.view_tag = cryptonote::get_output_view_tag(o);
enote_out.local_output_index = local_output_index;
@@ -240,6 +243,7 @@ static std::optional<enote_view_incoming_scan_info_t> view_incoming_scan_pre_car
.payment_id = payment_id,
.subaddr_index = subaddr_index,
.amount = amount,
.asset_type = enote.asset_type,
.amount_blinding_factor = amount_blinding_factor,
.main_tx_pubkey_index = main_deriv_idx
};
@@ -264,6 +268,7 @@ static std::optional<enote_view_incoming_scan_info_t> view_incoming_scan_carrot_
res.payment_id = crypto::null_hash;
res.subaddr_index = carrot::subaddress_index_extended{{0, 0}};
res.amount = enote.amount;
res.asset_type = enote.asset_type;
res.amount_blinding_factor = rct::I;
res.main_tx_pubkey_index = 0;
@@ -309,6 +314,7 @@ static std::optional<enote_view_incoming_scan_info_t> view_incoming_scan_carrot_
res.subaddr_index.reset();
res.amount_blinding_factor = rct::sk2rct(amount_blinding_factor_sk);
res.main_tx_pubkey_index = 0;
res.asset_type = enote.asset_type;
return res;
}
@@ -358,6 +364,7 @@ static std::optional<enote_view_incoming_scan_info_t> view_incoming_scan_carrot_
res.subaddr_index = subaddr_index;
res.amount_blinding_factor = rct::sk2rct(amount_blinding_factor_sk);
res.main_tx_pubkey_index = 0;
res.asset_type = enote.asset_type;
return res;
}

View File

@@ -81,6 +81,9 @@ struct PreCarrotEnote
crypto::public_key onetime_address;
boost::optional<crypto::view_tag> view_tag;
// asset type
std::string asset_type;
std::size_t local_output_index;
bool encrypted_amount;

View File

@@ -2630,6 +2630,9 @@ void wallet2::process_new_scanned_transaction(
output_tracker_cache[std::make_pair(tx.vout.at(td.m_internal_output_index).amount, td.m_global_output_index)] =
m_transfers.size() - 1;
// update m_transfer_indices
m_transfers_indices[enote_scan_info->asset_type].insert(m_transfers.size()-1);
// update multisig info
if (m_multisig)
{