forked from townforge/townforge
cc: fix infinite loop processing mortgages
This commit is contained in:
parent
d8d45c8fba
commit
ca331ca4a9
@ -1663,7 +1663,8 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
|
||||
// mortgages
|
||||
const uint64_t mortgage_height = top_height + 1;
|
||||
CHECK_AND_ASSERT_THROW_MES(mortgage_height % GAME_UPDATE_FREQUENCY == 0, "Mortgage height is not a multiple of " << GAME_UPDATE_FREQUENCY);
|
||||
bool ret = db.for_all_cc_custom_items([&db, &cg, &events, &balance_deltas, &item_balance_deltas, &item_count_deltas, &item_owners, mortgage_height](const cc::cc_custom_item_t &cid) {
|
||||
std::vector<cc::cc_custom_item_t> mortgages;
|
||||
bool ret = db.for_all_cc_custom_items([&mortgages, mortgage_height](const cc::cc_custom_item_t &cid) {
|
||||
const bool is_mortgage = !cid.is_group && cid.group == MORTGAGE_ITEM_GROUP;
|
||||
if (!is_mortgage)
|
||||
return true;
|
||||
@ -1673,22 +1674,34 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
|
||||
const cc::mortgage_phase_t phase = cc::get_mortgage_phase(mortgage_height, cid.creation_height, num_ticks_delay, num_tick_payments);
|
||||
if (phase == cc::mortgage_phase_delay || phase == cc::mortgage_phase_paid)
|
||||
return true;
|
||||
mortgages.push_back(cid);
|
||||
return true;
|
||||
});
|
||||
CHECK_AND_ASSERT_THROW_MES(ret, "Error processing mortgages");
|
||||
for (const cc::cc_custom_item_t &cid: mortgages)
|
||||
{
|
||||
uint32_t flag, item, num_ticks_delay, num_tick_payments;
|
||||
uint64_t tick_payment, maturity_payment;
|
||||
cc::get_mortgage_data(cid.user_data, flag, item, tick_payment, maturity_payment, num_ticks_delay, num_tick_payments);
|
||||
const cc::mortgage_phase_t phase = cc::get_mortgage_phase(mortgage_height, cid.creation_height, num_ticks_delay, num_tick_payments);
|
||||
CHECK_AND_ASSERT_THROW_MES(phase != cc::mortgage_phase_delay && phase != cc::mortgage_phase_paid, "Wrong phase, should have been rejected already");
|
||||
const uint64_t amount = db.get_cc_item_count(cid.id);
|
||||
if (amount == 0)
|
||||
return true;
|
||||
continue;
|
||||
cryptonote::cc_flag_data_t fd;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_flag_data(flag, fd), true, "Failed to get mortgaged flag data"); // flag does not exist anymore -> success, ignored
|
||||
if (!db.get_cc_flag_data(flag, fd)) // flag does not exist anymore -> success, ignored
|
||||
continue;
|
||||
if (fd.owner == FORECLOSURE_ACCOUNT)
|
||||
return true;
|
||||
CHECK_AND_ASSERT_MES(fd.owner == cid.creator, false, "Mortgaged flag owner is neither mortgage creator nor foreclosure account");
|
||||
continue;
|
||||
CHECK_AND_ASSERT_THROW_MES(fd.owner == cid.creator, "Mortgaged flag owner is neither mortgage creator nor foreclosure account");
|
||||
const std::string flag_name = fd.name.empty() ? "Flag " + std::to_string(fd.id) : fd.name;
|
||||
const uint64_t payment = phase == cc::mortgage_phase_maturity ? maturity_payment : tick_payment;
|
||||
uint64_t actual_payment = payment;
|
||||
cryptonote::cc_account_data_t ad;
|
||||
CHECK_AND_ASSERT_MES(db.get_cc_account_data(cid.creator, ad), false, "Failed to get account data");
|
||||
CHECK_AND_ASSERT_THROW_MES(db.get_cc_account_data(cid.creator, ad), "Failed to get account data");
|
||||
if (item == 0)
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(payment <= std::numeric_limits<uint64_t>::max() / amount, false, "Payment overflow");
|
||||
CHECK_AND_ASSERT_THROW_MES(payment <= std::numeric_limits<uint64_t>::max() / amount, "Payment overflow");
|
||||
const uint64_t balance = ad.balance + balance_deltas[ad.id];
|
||||
if (balance < payment * amount)
|
||||
{
|
||||
@ -1698,7 +1711,7 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(payment <= std::numeric_limits<uint32_t>::max() / amount, false, "Payment overflow");
|
||||
CHECK_AND_ASSERT_THROW_MES(payment <= std::numeric_limits<uint32_t>::max() / amount, "Payment overflow");
|
||||
const auto i = ad.item_balances.find(item);
|
||||
const uint32_t item_balance = (i == ad.item_balances.end() ? 0 : i->second) + item_balance_deltas[std::make_pair(ad.id, item)];
|
||||
if (item_balance < payment * amount)
|
||||
@ -1749,7 +1762,7 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
|
||||
creator_name = "<error>";
|
||||
events.add(cg, FORECLOSURE_ACCOUNT, flag) << "Received " << flag_name << " due to " << creator_name << " defaulting on mortgage payment";
|
||||
const uint64_t maturity_height = cc::get_mortgage_maturity_height(cid.creation_height, num_ticks_delay, num_tick_payments);
|
||||
CHECK_AND_ASSERT_MES(maturity_height % GAME_UPDATE_FREQUENCY == 0, false, "Maturity height is not a multiple of " << GAME_UPDATE_FREQUENCY);
|
||||
CHECK_AND_ASSERT_THROW_MES(maturity_height % GAME_UPDATE_FREQUENCY == 0, "Maturity height is not a multiple of " << GAME_UPDATE_FREQUENCY);
|
||||
const uint64_t ticks = std::min<uint64_t>((maturity_height - mortgage_height) / GAME_UPDATE_FREQUENCY + 1, num_tick_payments);
|
||||
const uint64_t debt_per_share = ticks * tick_payment + maturity_payment - actual_payment; // overflow checked at command creation
|
||||
MINFO(ad.name << " defaults on " << flag_name << " mortgage, owes " << (item ? std::to_string(debt_per_share) + " " + cc::get_item_name(db, item) : cryptonote::print_money(debt_per_share)) << " per share on " << amount << " shares");
|
||||
@ -1767,10 +1780,7 @@ static void add_cities(const BlockchainDB &db, uint8_t version, cc_command_game_
|
||||
}
|
||||
cg.maturing_mortgages.push_back(cid.id);
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
CHECK_AND_ASSERT_THROW_MES(ret, "Error processing mortgages");
|
||||
}
|
||||
|
||||
// auctions
|
||||
const uint64_t auction_height = top_height + 1;
|
||||
|
Loading…
Reference in New Issue
Block a user