change is once again working in the wallet - this only leaves the converted amounts to be paid out, and yield TXs to be supported

This commit is contained in:
Some Random Crypto Guy
2023-11-21 21:22:21 +00:00
parent ef27f6380e
commit c1f5dd42e8
12 changed files with 285 additions and 170 deletions
+133 -81
View File
@@ -369,9 +369,7 @@ typedef struct outassettype {
typedef struct circ_supply {
crypto::hash tx_hash;
//uint64_t pricing_record_height;
uint64_t source_currency_type;
uint64_t dest_currency_type;
uint32_t asset_type;
uint64_t amount_burnt;
uint64_t amount_minted;
} circ_supply;
@@ -944,25 +942,22 @@ import_tally_from_cst(circ_supply_tally *cst)
return tally;
}
boost::multiprecision::int128_t
read_circulating_supply_data(MDB_cursor *cur_circ_supply_tally, MDB_val idx)
int read_circulating_supply_data(MDB_cursor *cur_circ_supply_tally, MDB_val idx, boost::multiprecision::int128_t& tally)
{
MDB_val vcst;
circ_supply_tally cst;
int result = mdb_cursor_get(cur_circ_supply_tally, &idx, &vcst, MDB_SET);
if (result == MDB_NOTFOUND) {
LOG_PRINT_L1("Failed to obtain circulating supply - must be first TX with this asset");
cst.is_negative = false;
cst.amount_hi = 0;
cst.amount_lo = 0;
tally = 0;
} else if (!result) {
cst = *(circ_supply_tally*) vcst.mv_data;
tally = import_tally_from_cst(&cst);
} else {
throw0(DB_ERROR(lmdb_error("Failed to obtain tally for circulating supply: ", result).c_str()));
throw0(DB_ERROR(lmdb_error("Failed to obtain tally for circulating supply: ", result).c_str()));
tally = -1;
}
return import_tally_from_cst(&cst);
return result;
}
void write_circulating_supply_data(MDB_cursor *cur_circ_supply_tally, MDB_val idx, boost::multiprecision::int128_t tally)
@@ -1078,23 +1073,13 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
throw0(DB_ERROR(lmdb_error("Failed to add prunable tx prunable hash to db transaction: ", result).c_str()));
}
// get tx assets
std::string strSource;
std::string strDest;
if (!get_tx_asset_types(tx, tx_hash, strSource, strDest, miner_tx)) {
throw0(DB_ERROR("Failed to add tx circulating supply to db transaction: get_tx_asset_types fails."));
}
if (strSource != strDest) {
if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN) {
// Conversion TX - update our records
circ_supply cs;
cs.tx_hash = tx_hash;
//cs.pricing_record_height = tx.pricing_record_height;
cs.source_currency_type = std::find(oracle::ASSET_TYPES.begin(), oracle::ASSET_TYPES.end(), strSource) - oracle::ASSET_TYPES.begin();
cs.dest_currency_type = std::find(oracle::ASSET_TYPES.begin(), oracle::ASSET_TYPES.end(), strDest) - oracle::ASSET_TYPES.begin();
cs.asset_type = cryptonote::asset_id_from_type(tx.source_asset_type);
cs.amount_burnt = tx.amount_burnt;
// SRCG - need to work out how to populate this
//cs.amount_minted = tx.amount_minted;
cs.amount_minted = 0;
MDB_val_set(val_circ_supply, cs);
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
@@ -1102,27 +1087,67 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
// Get the current tally value for the source currency type
MDB_val_copy<uint64_t> source_idx(cs.source_currency_type);
boost::multiprecision::int128_t source_tally = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx);
MDB_val_copy<uint64_t> source_idx(cs.asset_type);
boost::multiprecision::int128_t source_tally = 0;
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
boost::multiprecision::int128_t final_source_tally = source_tally - cs.amount_burnt;
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
if ((strSource == "FULM" && (coinbase + final_source_tally < 0)) ||
(strSource != "FULM" && final_source_tally < 0)) {
LOG_ERROR(__func__ << " : mint/burn underflow detected for " << strSource << " : correcting supply tally by " << final_source_tally);
final_source_tally = 0;
if (source_tally == 0 && result == MDB_NOTFOUND) {
if (tx.source_asset_type == "FULM") {
final_source_tally += coinbase;
} else {
throw0(DB_ERROR("burn underflow - asset balance is zero for non-FULM asset"));
}
}
write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally);
// Get the current tally value for the dest currency type
MDB_val_copy<uint64_t> dest_idx(cs.dest_currency_type);
boost::multiprecision::int128_t dest_tally = read_circulating_supply_data(m_cur_circ_supply_tally, dest_idx);
boost::multiprecision::int128_t final_dest_tally = dest_tally + cs.amount_minted;
write_circulating_supply_data(m_cur_circ_supply_tally, dest_idx, final_dest_tally);
LOG_PRINT_L1("tx ID " << tx_id << "\nSource tally before burn =" << source_tally.str() << "\nSource tally after burn =" << final_source_tally.str() <<
"\nDest tally before mint =" << dest_tally.str() << "\nDest tally after mint =" << final_dest_tally.str());
LOG_PRINT_L1("tx ID " << tx_id << "\n\tTally before burn = " << source_tally.str() << "\n\tTally after burn = " << final_source_tally.str());
}
if (tx.type == cryptonote::transaction_type::PROTOCOL) {
// Iterate over all of the outputs for a PROTOCOL_TX since they're all MINTED
std::map<uint32_t, uint64_t> minted_amounts;
for (const auto& out: tx.vout) {
// Fetch the amount and output_asset_type for this output
std::string asset_type = "";
bool ok = cryptonote::get_output_asset_type(out, asset_type);
if (!ok)
throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)"));
circ_supply cs;
cs.tx_hash = tx_hash;
cs.asset_type = cryptonote::asset_id_from_type(asset_type);
cs.amount_burnt = 0;
cs.amount_minted = out.amount;
minted_amounts[cs.asset_type] += out.amount;
MDB_val_set(val_circ_supply, cs);
result = mdb_cursor_put(m_cur_circ_supply, &val_tx_id, &val_circ_supply, MDB_APPEND);
if (result)
throw0(DB_ERROR( lmdb_error("Failed to add tx circulating supply to db transaction: ", result).c_str() ));
}
// Now update the overall tally entries
for (const auto& asset: minted_amounts) {
// Get the current tally value for the source currency type
MDB_val_copy<uint64_t> source_idx(asset.first);
boost::multiprecision::int128_t source_tally = 0;
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
boost::multiprecision::int128_t final_source_tally = source_tally + asset.second;
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
if (source_tally == 0 && result == MDB_NOTFOUND) {
if (tx.source_asset_type == "FULM") {
final_source_tally += coinbase;
}
}
write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally);
LOG_PRINT_L1("tx ID " << tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before burn =" << source_tally.str() << "\n\tTally after burn =" << final_source_tally.str());
}
}
// Is there yield_tx data to add?
if (tx.type == cryptonote::transaction_type::YIELD) {
// Create the object we are going to write to the database
@@ -1203,55 +1228,64 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
throw1(DB_ERROR(lmdb_error("Failed to add removal of prunable hash tx to db transaction: ", result).c_str()));
}
// get tx assets
std::string strSource;
std::string strDest;
if (!get_tx_asset_types(tx, tx_hash, strSource, strDest, miner_tx)) {
throw0(DB_ERROR("Failed to add tx circulating supply to db transaction: get_tx_asset_types fails."));
if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN) {
// Get the current tally value for the source currency type
MDB_val_copy<uint64_t> source_idx(cryptonote::asset_id_from_type(tx.source_asset_type));
boost::multiprecision::int128_t source_tally = 0;
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
if (result == MDB_NOTFOUND)
throw0(DB_ERROR("remove_transaction_data() - minted asset not found"));
boost::multiprecision::int128_t final_source_tally = source_tally + tx.amount_burnt;
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally);
LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tTally before remint =" << source_tally.str() << "\n\tTally after remint =" << final_source_tally.str());
}
if (strSource != strDest)
{
// Update the tally table
// Get the current tally value for the source currency type
circ_supply cs;
cs.tx_hash = tx_hash;
//cs.pricing_record_height = tx.pricing_record_height;
cs.amount_burnt = tx.amount_burnt;
// SRCG - need to work out how to populate this
//cs.amount_minted = tx.amount_minted;
cs.source_currency_type = std::find(oracle::ASSET_TYPES.begin(), oracle::ASSET_TYPES.end(), strSource) - oracle::ASSET_TYPES.begin();
cs.dest_currency_type = std::find(oracle::ASSET_TYPES.begin(), oracle::ASSET_TYPES.end(), strDest) - oracle::ASSET_TYPES.begin();
if (tx.type == cryptonote::transaction_type::PROTOCOL) {
// Update the tally by increasing the amount by how much we've burnt
MDB_val_copy<uint64_t> source_idx(cs.source_currency_type);
boost::multiprecision::int128_t source_tally = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx);
boost::multiprecision::int128_t final_source_tally = source_tally + cs.amount_burnt;
write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally);
// Update the tally by decreasing the amount by how much we've minted
MDB_val_copy<uint64_t> dest_idx(cs.dest_currency_type);
boost::multiprecision::int128_t dest_tally = read_circulating_supply_data(m_cur_circ_supply_tally, dest_idx);
boost::multiprecision::int128_t final_dest_tally = dest_tally - cs.amount_minted;
boost::multiprecision::int128_t coinbase = get_block_already_generated_coins(m_height-1);
if ((strDest == "FULM" && (coinbase + final_dest_tally < 0)) ||
(strDest != "FULM" && final_dest_tally < 0)) {
LOG_ERROR(__func__ << " : mint/burn underflow detected for " << strDest << " : correcting supply tally by " << final_dest_tally);
final_dest_tally = 0;
// Iterate over all of the outputs for a PROTOCOL_TX since they're all MINTED
std::map<uint32_t, uint64_t> minted_amounts;
for (const auto& out: tx.vout) {
// Fetch the amount and output_asset_type for this output
std::string asset_type = "";
bool ok = cryptonote::get_output_asset_type(out, asset_type);
if (!ok)
throw0(DB_ERROR("failed to get output asset type (needed to update the circulating supply data for the PROTOCOL_TX)"));
minted_amounts[cryptonote::asset_id_from_type(asset_type)] += out.amount;
}
write_circulating_supply_data(m_cur_circ_supply_tally, dest_idx, final_dest_tally);
// Update the circ_supply table
if ((result = mdb_cursor_get(m_cur_circ_supply, &val_tx_id, NULL, MDB_SET)))
// Now update the overall tally entries
for (const auto& asset: minted_amounts) {
// Get the current tally value for the source currency type
MDB_val_copy<uint64_t> source_idx(asset.first);
boost::multiprecision::int128_t source_tally = 0;
result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally);
if (result == MDB_NOTFOUND)
throw0(DB_ERROR("remove_transaction_data() - minted asset not found"));
if (source_tally < asset.second)
throw0(DB_ERROR("remove_transaction_data() - mint underflow"));
boost::multiprecision::int128_t final_source_tally = source_tally - asset.second;
write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally);
LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\n\tAsset Type = " << cryptonote::asset_type_from_id(asset.first) << "\n\tTally before undoing mint =" << source_tally.str() << "\n\tTally after undoing mint =" << final_source_tally.str());
}
}
// Update the circ_supply table by deleting all entries for this TX
if ((result = mdb_cursor_get(m_cur_circ_supply, &val_tx_id, NULL, MDB_SET))) {
if (result == MDB_NOTFOUND) {
LOG_PRINT_L1("failed to obtain circulating supply data - no burns / conversions made yet?");
} else {
throw1(DB_ERROR(lmdb_error("Failed to locate circulating supply for removal: ", result).c_str()));
}
} else {
result = mdb_cursor_del(m_cur_circ_supply, 0);
if (result)
throw1(DB_ERROR(lmdb_error("Failed to add removal of circulating supply to db transaction: ", result).c_str()));
LOG_PRINT_L1("tx ID " << tip->data.tx_id << "\nSource tally before undoing burn =" << source_tally.str() << "\nSource tally after undoing burn =" << final_source_tally.str() <<
"\nDest tally before undoing mint =" << dest_tally.str() << "\nDest tally after undoing mint =" << final_dest_tally.str());
}
remove_tx_outputs(tip->data.tx_id, tx);
result = mdb_cursor_get(m_cur_tx_outputs, &val_tx_id, NULL, MDB_SET);
@@ -1763,6 +1797,8 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
lmdb_db_open(txn, LMDB_CIRC_SUPPLY, MDB_INTEGERKEY | MDB_CREATE, m_circ_supply, "Failed to open db handle for m_circ_supply");
lmdb_db_open(txn, LMDB_CIRC_SUPPLY_TALLY, MDB_CREATE, m_circ_supply_tally, "Failed to open db handle for m_circ_supply_tally");
lmdb_db_open(txn, LMDB_YIELD_TXS, MDB_INTEGERKEY | MDB_DUPSORT | MDB_DUPFIXED | MDB_CREATE, m_yield_txs, "Failed to open db handle for m_yield_txs");
mdb_set_dupsort(txn, m_spent_keys, compare_hash32);
mdb_set_dupsort(txn, m_block_heights, compare_hash32);
mdb_set_dupsort(txn, m_tx_indices, compare_hash32);
@@ -1784,6 +1820,8 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
mdb_set_compare(txn, m_circ_supply, compare_uint64);
mdb_set_compare(txn, m_circ_supply_tally, compare_uint64);
mdb_set_dupsort(txn, m_yield_txs, compare_uint64);
if (!(mdb_flags & MDB_RDONLY))
{
result = mdb_drop(txn, m_hf_starting_heights, 1);
@@ -1960,6 +1998,8 @@ void BlockchainLMDB::reset()
throw0(DB_ERROR(lmdb_error("Failed to drop m_hf_versions: ", result).c_str()));
if (auto result = mdb_drop(txn, m_properties, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_properties: ", result).c_str()));
if (auto result = mdb_drop(txn, m_yield_txs, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_yield_txs: ", result).c_str()));
// init with current version
MDB_val_str(k, "version");
@@ -3287,7 +3327,7 @@ std::map<std::string,uint64_t> BlockchainLMDB::get_circulating_supply() const
// Push the data into the circulating supply return struct
const uint64_t currency_type = *(const uint64_t*)k.mv_data;
circ_supply_tally *cst = (circ_supply_tally*)v.mv_data;
const std::string currency_label = oracle::ASSET_TYPES.at(currency_type);
const std::string currency_label = cryptonote::asset_type_from_id(currency_type);
boost::multiprecision::int128_t amount = import_tally_from_cst(cst);
// Check for FULM - we need to adjust the total for them
@@ -3592,12 +3632,24 @@ bool BlockchainLMDB::get_blocks_from(uint64_t start_height, size_t min_block_cou
if (result)
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve transaction data from the db: ", result).c_str()));
}
// Skip the protocol TX as well?
op = MDB_NEXT;
result = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &v, op);
if (result)
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve transaction data from the db: ", result).c_str()));
if (!pruned)
{
result = mdb_cursor_get(m_cur_txs_prunable, &val_tx_id, &v, op);
if (result)
throw0(DB_ERROR(lmdb_error("Error attempting to retrieve transaction data from the db: ", result).c_str()));
}
}
op = MDB_NEXT;
current_block.second.reserve(b.tx_hashes.size());
num_txes += b.tx_hashes.size() + (skip_coinbase ? 0 : 1);
num_txes += b.tx_hashes.size() + (skip_coinbase ? 0 : 2);
for (const auto &tx_hash: b.tx_hashes)
{
// get pruned data