fix inventory bug with mortgages that mature while being auctioned

This commit is contained in:
Crypto City 2021-06-24 08:50:19 +00:00
parent 1928507a29
commit bf5e9909d2
3 changed files with 121 additions and 3 deletions

View File

@ -270,7 +270,6 @@ bool cc_command_handler_game_update::execute(cryptonote::BlockchainDB &db, const
{
cc::auction_t ad;
CHECK_AND_ASSERT_MES(db.get_cc_auction_data(e, ad), false, "Failed to get auction data");
CHECK_AND_ASSERT_MES(!ad.bids.empty(), false, "Auction bids are empty");
std::map<uint32_t, uint64_t> reserves;
for (const auto &e: ad.bids)
@ -278,7 +277,7 @@ bool cc_command_handler_game_update::execute(cryptonote::BlockchainDB &db, const
for (const auto &e: reserves)
db.unreserve_cc_account_balance(e.first, FORECLOSURE_ACCOUNT, e.second);
const uint32_t buyer = std::get<0>(ad.bids.back());
const uint32_t buyer = ad.bids.empty() ? ad.seller : std::get<0>(ad.bids.back());
switch (ad.type)
{
case cc::auction_t::type_flag:
@ -671,7 +670,6 @@ bool cc_command_handler_game_update::revert(cryptonote::BlockchainDB &db, const
cc::auction_t ad;
db.set_cc_auction_ended(e, false);
CHECK_AND_ASSERT_MES(db.get_cc_auction_data(e, ad), false, "Failed to get auction data");
CHECK_AND_ASSERT_MES(!ad.bids.empty(), false, "Auction bids are empty");
std::map<uint32_t, uint64_t> reserves;
for (const auto &e: ad.bids)
reserves[std::get<0>(e)] = std::get<1>(e);

View File

@ -1663,6 +1663,31 @@ static void add_cities(const BlockchainDB &db, cc_command_game_update_t &cg, gam
cg.auction_ends.push_back(auction.id);
return true;
}
if (auction.type == cc::auction_t::type_item)
{
for (const auto &e: auction.entries)
{
const uint32_t item_id = e.first;
if (item_id < ITEM_FIRST_USER || item_id > ITEM_LAST_USER)
continue;
cc::cc_custom_item_t cid;
if (!db.get_cc_custom_item_data(item_id, cid))
{
MERROR("Failed to get auctioned item data, closing auction");
cg.auction_ends.push_back(auction.id);
return true;
}
const bool is_mortgage = !cid.is_group && cid.group == MORTGAGE_ITEM_GROUP;
if (!is_mortgage)
continue;
if (std::find(cg.maturing_mortgages.begin(), cg.maturing_mortgages.end(), cid.id) != cg.maturing_mortgages.end())
{
MERROR("Auctioned mortgage is maturing, closing auction");
cg.auction_ends.push_back(auction.id);
return true;
}
}
}
const std::pair<uint64_t, bool> end_time = cc::get_auction_end_time(auction, auction_height);
if (end_time.first < auction_height)
MWARNING("Auction ends in the past! Ending now");

View File

@ -129,6 +129,7 @@ AUCTION_BID_FEE = 10000000
MIN_AUCTION_BASE_TICKS = 8
MAX_AUCTION_BASE_TICKS = 56
BADGE_COSMOPOLITAN = 49
CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE = 20
def COIN_TYPE(x):
return x[0] >> 56
@ -1679,6 +1680,100 @@ class CCTest():
res = daemon.cc_get_account(account_id[i])
assert (self.remove_wood(res.item_balances if 'item_balances' in res else [])) == self.remove_wood(expected_item_balances[i])
print('Testing maturing mortage auctions')
# create new flag
res = self.wallet[2].cc_buy_items(entries = [{'type': ITEM_STONE, 'amount': 8192}, {'type': ITEM_WOOD, 'amount': 25000}, {'type': ITEM_LABOUR, 'amount': 250000}])
res = daemon.cc_get_new_flag_cost(0, FIRST_CITY_X - 1200, FIRST_CITY_Y - 400, FIRST_CITY_X - 1200 + 64 - 1, FIRST_CITY_Y - 400 + 64 - 1)
res = self.wallet[2].cc_buy_land(FIRST_CITY_X - 1200, FIRST_CITY_Y - 400, FIRST_CITY_X - 1200 + 64 - 1, FIRST_CITY_Y - 400 + 64 - 1)
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
res = daemon.cc_get_account(account_id[2])
flag_id = res.flags[-1]
res = daemon.cc_get_flag(flag_id)
construction_height = res.construction_height
res = self.wallet[2].cc_building_settings(flag_id, ROLE_RESIDENTIAL1, 100, construction_height)
assert len(res.tx_hash) == 64
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
# mortgage it
res = daemon.get_height()
height = res.height
res = self.wallet[2].cc_create_mortgage(flag_id, "test mortgage auction", "test", ITEM_LABOUR, 2, 10, 0, 2, 3)
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
res = daemon.cc_get_account(account_id[2])
item_id = res.item_balances[-1]['type']
res = daemon.cc_get_custom_items([item_id])
assert 'items_' in res and len(res.items_) == 1
assert res.items_[0].id == item_id
assert res.items_[0].name == "test mortgage auction"
assert not res.items_[0].is_group
assert res.items_[0].group == MORTGAGE_ITEM_GROUP
assert res.items_[0].creator == account_id[2]
assert res.items_[0].amount == 3
# auction mortgage in three lots
auction_id = [0, 0, 0]
for i in range(3):
res = self.wallet[2].cc_create_auction(AUCTION_TYPE_ITEM, [{'object': item_id, 'amount': 1}], MIN_AUCTION_BASE_TICKS)
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
res = daemon.cc_get_auctions()
auction_id[i] = res.auctions[-1].id
# bid on one, have another bid on another, and leave the last one alone
res = self.wallet[2].cc_transfer(self.pkeys[1], amount = AUCTION_BID_FEE + 500)
self.generate_blocks('TF1MM8HqWBathu8hS5mwMNHm1da3cZCzg2rkqWLKCxpUarKtPszP3MjiocrJeLvph4AghgYu1AXonCmckfEuyE8Q2FFm8jNdiz3', 1)
self.wallet[2].refresh()
self.wallet[2].cc_auction_bid(auction_id[2], 500)
self.wallet[1].refresh()
self.wallet[1].cc_auction_bid(auction_id[1], 500)
# wait till the end of the auctions
res = daemon.get_info()
height = res.height
blocks = (GAME_UPDATE_FREQUENCY * 8000 - height) % GAME_UPDATE_FREQUENCY + 1
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', blocks)
blocks = (MIN_AUCTION_BASE_TICKS + 2) * GAME_UPDATE_FREQUENCY + GAME_UPDATE_FREQUENCY
while blocks > 0:
self.generate_blocks('TF1MMBg4zx18SnZC6oswCRB7DzdVeUKce5NdCMSWUHNY4wNvNhzmFj4WqZY2bFj8R1REAWR3qAH5zD7sjXyHz3tVayzHSswqymx', GAME_UPDATE_FREQUENCY)
blocks -= GAME_UPDATE_FREQUENCY
# they should all be over, including the one that did not get any bid, since the item is gone
res = daemon.cc_get_auctions()
auction_found = [False, False, False]
if 'auctions' in res:
for e in res.auctions:
for i in range(3):
if e.id == auction_id[i]:
print('found auction: ' + str(e))
assert not auction_found[i]
auction_found[i] = True
assert not auction_found[0]
assert not auction_found[1]
assert not auction_found[2]
# there should be no item left, and inventories/reserves should not have any either
res = daemon.cc_get_custom_items([item_id])
assert len(res.items_) == 1
assert res.items_[0].amount == 0
res = daemon.cc_get_item_count([item_id])
assert len(res.counts) == 1
assert res.counts[0] == 0
res = daemon.cc_get_item_ownership(item_id)
assert 'ownership' not in res or len(res.ownership) == 0
for i in range(len(account_id)):
res = daemon.cc_get_account(account_id[i])
for e in res.item_balances:
assert e.type != item_id
if 'reserves' in res:
for f in res.reserves:
if 'items_' in f:
for e in f.items_:
assert e.type != item_id
def test_trading(self):
daemon = self.daemon