Fix ringct+coinbase output tracking, and update rescan rollbacks (#178)

This commit is contained in:
Lee *!* Clagett
2025-09-04 23:14:03 -04:00
committed by Lee *!* Clagett
parent 44278d0d11
commit a11482c123
5 changed files with 57 additions and 28 deletions

View File

@@ -2100,7 +2100,7 @@ namespace db
{
//! \return Success, even if `address` was not found (designed for
expect<void>
change_height(MDB_cursor& accounts_cur, MDB_cursor& accounts_ba_cur, MDB_cursor& accounts_bh_cur, block_id height, account_address const& address)
change_height(MDB_cursor& accounts_cur, MDB_cursor& accounts_ba_cur, MDB_cursor& accounts_bh_cur, MDB_cursor& outputs_cur, MDB_cursor& spends_cur, MDB_cursor& images_cur, block_id height, account_address const& address)
{
MDB_val key = lmdb::to_val(by_address_version);
MDB_val value = lmdb::to_val(address);
@@ -2146,6 +2146,9 @@ namespace db
mdb_cursor_put(&accounts_bh_cur, &key, &value, MDB_NODUPDATA)
);
MONERO_CHECK(rollback_outputs(user->id, height, outputs_cur));
MONERO_CHECK(rollback_spends(user->id, height, spends_cur, images_cur));
return success();
}
}
@@ -2180,15 +2183,21 @@ namespace db
cursor::accounts accounts_cur;
cursor::accounts_by_address accounts_ba_cur;
cursor::accounts_by_height accounts_bh_cur;
cursor::outputs outputs_cur;
cursor::spends spends_cur;
cursor::images images_cur;
MONERO_CHECK(check_cursor(txn, this->db->tables.accounts, accounts_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.accounts_ba, accounts_ba_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.accounts_bh, accounts_bh_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.outputs, outputs_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.spends, spends_cur));
MONERO_CHECK(check_cursor(txn, this->db->tables.images, images_cur));
for (account_address const& address : addresses)
{
const expect<void> changed = change_height(
*accounts_cur, *accounts_ba_cur, *accounts_bh_cur, height, address
*accounts_cur, *accounts_ba_cur, *accounts_bh_cur, *outputs_cur, *spends_cur, *images_cur, height, address
);
if (changed)
updated.push_back(address);
@@ -2421,11 +2430,17 @@ namespace db
cursor::accounts accounts_ba_cur;
cursor::accounts accounts_bh_cur;
cursor::requests requests_cur;
cursor::outputs outputs_cur;
cursor::spends spends_cur;
cursor::images images_cur;
MONERO_CHECK(check_cursor(txn, tables.accounts, accounts_cur));
MONERO_CHECK(check_cursor(txn, tables.accounts_ba, accounts_ba_cur));
MONERO_CHECK(check_cursor(txn, tables.accounts_bh, accounts_bh_cur));
MONERO_CHECK(check_cursor(txn, tables.requests, requests_cur));
MONERO_CHECK(check_cursor(txn, tables.outputs, outputs_cur));
MONERO_CHECK(check_cursor(txn, tables.spends, spends_cur));
MONERO_CHECK(check_cursor(txn, tables.images, images_cur));
const request req = request::import_scan;
for (account_address const& address : addresses)
@@ -2445,7 +2460,7 @@ namespace db
return new_height.error();
const expect<void> changed = change_height(
*accounts_cur, *accounts_ba_cur, *accounts_bh_cur, *new_height, address
*accounts_cur, *accounts_ba_cur, *accounts_bh_cur, *outputs_cur, *spends_cur, *images_cur, *new_height, address
);
if (changed)
updated.push_back(address);

View File

@@ -107,21 +107,27 @@ namespace
rct_bytes rct{};
rct_bytes const* optional_rct = nullptr;
if (unpack(self.data.first.extra).first & lws::db::ringct_output)
const auto flags = unpack(self.data.first.extra).first;
if (flags & lws::db::ringct_output)
{
crypto::key_derivation derived;
if (!crypto::generate_key_derivation(self.data.first.spend_meta.tx_public, self.user_key, derived))
MONERO_THROW(lws::error::crypto_failure, "generate_key_derivation failed");
if (!(flags & lws::db::coinbase_output))
{
crypto::key_derivation derived;
if (!crypto::generate_key_derivation(self.data.first.spend_meta.tx_public, self.user_key, derived))
MONERO_THROW(lws::error::crypto_failure, "generate_key_derivation failed");
crypto::secret_key scalar;
rct::ecdhTuple encrypted{self.data.first.ringct_mask, rct::d2h(self.data.first.spend_meta.amount)};
crypto::secret_key scalar;
rct::ecdhTuple encrypted{self.data.first.ringct_mask, rct::d2h(self.data.first.spend_meta.amount)};
crypto::derivation_to_scalar(derived, self.data.first.spend_meta.index, scalar);
rct::ecdhEncode(encrypted, rct::sk2rct(scalar), false);
crypto::derivation_to_scalar(derived, self.data.first.spend_meta.index, scalar);
rct::ecdhEncode(encrypted, rct::sk2rct(scalar), false);
rct.commitment = rct::commit(self.data.first.spend_meta.amount, self.data.first.ringct_mask);
rct.mask = encrypted.mask;
rct.amount = encrypted.amount;
rct.commitment = rct::commit(self.data.first.spend_meta.amount, self.data.first.ringct_mask);
rct.mask = encrypted.mask;
rct.amount = encrypted.amount;
}
else
rct.mask = rct::identity();
optional_rct = std::addressof(rct);
}

View File

@@ -507,6 +507,8 @@ namespace lws
mask = decrypted->second;
ext = db::extra(ext | db::ringct_output);
}
else if (1 < tx.version)
ext = db::extra(ext | db::ringct_output);
if (extra_nonce)
{