diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 78184a564..f990950f1 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1179,21 +1179,38 @@ 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())); } + if (tx.type == cryptonote::transaction_type::MINER) { + + // Update the circulating supply tally because of potentially burnt block_reward proportion + MDB_val_copy source_idx(cryptonote::asset_id_from_type("SAL")); + boost::multiprecision::int128_t source_tally = 0; + result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally); + if (result && (m_height>0 || result != MDB_NOTFOUND)) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); + boost::multiprecision::int128_t final_source_tally = source_tally; + for (const auto& out: tx.vout) { + + // Sanity check - prevent overflow + if (final_source_tally > final_source_tally + out.amount) + throw0(DB_ERROR("numeric overflow detected when adding miner_tx for db transaction")); + + // Fetch the amount for this output + final_source_tally += out.amount; + } + write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); + 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::BURN || tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::STAKE) { // Get the current tally value for the source currency type MDB_val_copy 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); - boost::multiprecision::int128_t final_source_tally = source_tally - tx.amount_burnt; + boost::multiprecision::int128_t final_source_tally = source_tally - tx.amount_burnt - tx.rct_signatures.txnFee; 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 == "SAL") { - final_source_tally += coinbase; - } else { - throw0(DB_ERROR("burn underflow - asset balance is zero for non-SAL asset")); - } - } + if (result) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); write_circulating_supply_data(m_cur_circ_supply_tally, source_idx, final_source_tally); LOG_PRINT_L1("tx ID " << tx_id << "\n\tTally before burn = " << source_tally.str() << "\n\tTally after burn = " << final_source_tally.str()); } @@ -1219,6 +1236,8 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons MDB_val_copy 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) + throw0(DB_ERROR(lmdb_error("Failed to get circulating supply tally when adding db transaction: ", result).c_str())); 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) { @@ -1340,7 +1359,29 @@ 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())); } - if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN) { + if (tx.type == cryptonote::transaction_type::MINER) { + + // Update the circulating supply tally because of potentially burnt block_reward proportion + MDB_val_copy source_idx(cryptonote::asset_id_from_type("SAL")); + boost::multiprecision::int128_t source_tally = 0; + result = read_circulating_supply_data(m_cur_circ_supply_tally, source_idx, source_tally); + if (result && (m_height>0 || result != MDB_NOTFOUND)) + throw0(DB_ERROR(lmdb_error("remove_transaction_data() - Failed to get circulating supply tally when removing db transaction: ", result).c_str())); + boost::multiprecision::int128_t final_source_tally = source_tally; + for (const auto& out: tx.vout) { + + // Sanity check - prevent underflow + if (final_source_tally < final_source_tally - out.amount) + throw0(DB_ERROR("remove_transaction_data() - numeric underflow detected when removing miner_tx for db transaction")); + + // Fetch the amount for this output + final_source_tally -= out.amount; + } + 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 burn = " << source_tally.str() << "\n\tTally after burn = " << final_source_tally.str()); + } + + if (tx.type == cryptonote::transaction_type::CONVERT || tx.type == cryptonote::transaction_type::BURN || tx.type == cryptonote::transaction_type::STAKE) { // Get the current tally value for the source currency type MDB_val_copy source_idx(cryptonote::asset_id_from_type(tx.source_asset_type)); @@ -1348,8 +1389,10 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const 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); + // Sanity check - prevent overflow + if (source_tally > source_tally + tx.amount_burnt + tx.rct_signatures.txnFee) + throw0(DB_ERROR("remove_transaction_data() - numeric overflow detected when processing C/B/S for db transaction")); + boost::multiprecision::int128_t final_source_tally = source_tally + tx.amount_burnt + tx.rct_signatures.txnFee; 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()); } @@ -3416,10 +3459,9 @@ std::map BlockchainLMDB::get_circulating_supply() const LOG_PRINT_L3("BlockchainLMDB::" << __func__ << " - mined supply for SAL = " << m_coinbase); // SRCG: For V1, we can simply return this number, because there is no other source of coins - circulating_supply["SAL"] = m_coinbase; - return circulating_supply; + //circulating_supply["SAL"] = m_coinbase; + //return circulating_supply; - /* check_open(); TXN_PREFIX_RDONLY(); @@ -3461,7 +3503,6 @@ std::map BlockchainLMDB::get_circulating_supply() const circulating_supply["SAL"] = m_coinbase; } return circulating_supply; - */ } uint64_t BlockchainLMDB::num_outputs() const diff --git a/src/blockchain_utilities/blockchain_stats.cpp b/src/blockchain_utilities/blockchain_stats.cpp index f0a8e5adc..83483f71d 100644 --- a/src/blockchain_utilities/blockchain_stats.cpp +++ b/src/blockchain_utilities/blockchain_stats.cpp @@ -174,7 +174,7 @@ int main(int argc, char* argv[]) if (command_line::get_arg(vm, command_line::arg_help)) { - std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; + std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL; std::cout << desc_options << std::endl; return 1; } @@ -240,7 +240,7 @@ int main(int argc, char* argv[]) /* * The default output can be plotted with GnuPlot using these commands: set key autotitle columnhead -set title "Monero Blockchain Growth" +set title "Salvium Blockchain Growth" set timefmt "%Y-%m-%d" set xdata time set xrange ["2014-04-17":*] diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 90e7c83fa..67eaa4eaf 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -209,7 +209,7 @@ namespace cryptonote static const command_line::arg_descriptor arg_block_rate_notify = { "block-rate-notify" , "Run a program when the block rate undergoes large fluctuations. This might " - "be a sign of large amounts of hash rate going on and off the Monero network, " + "be a sign of large amounts of hash rate going on and off the Salvium network, " "and thus be of potential interest in predicting attacks. %t will be replaced " "by the number of minutes for the observation window, %b by the number of " "blocks observed within that window, and %e by the number of blocks that was " @@ -1294,6 +1294,7 @@ namespace cryptonote std::vector txs; std::vector missed_txs; uint64_t coinbase_amount = get_outs_money_amount(b.miner_tx); + coinbase_amount += b.miner_tx.amount_burnt; this->get_transactions(b.tx_hashes, txs, missed_txs, true); uint64_t tx_fee_amount = 0; for(const auto& tx: txs) @@ -1829,7 +1830,7 @@ namespace cryptonote { std::string main_message; if (m_offline) - main_message = "The daemon is running offline and will not attempt to sync to the Monero network."; + main_message = "The daemon is running offline and will not attempt to sync to the Salvium network."; else main_message = "The daemon will start synchronizing with the network. This may take a long time to complete."; MGINFO_YELLOW(ENDL << "**********************************************************************" << ENDL @@ -2072,7 +2073,7 @@ namespace cryptonote MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")"); if (p < threshold) { - MWARNING("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Monero network or under attack, or your computer's time is off. Or it could be just sheer bad luck."); + MWARNING("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Salvium network or under attack, or your computer's time is off. Or it could be just sheer bad luck."); std::shared_ptr block_rate_notify = m_block_rate_notify; if (block_rate_notify) diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index 2758d83f2..1831b9f29 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -35,7 +35,7 @@ namespace daemon_args { - std::string const WINDOWS_SERVICE_NAME = "Monero Daemon"; + std::string const WINDOWS_SERVICE_NAME = "Salvium Daemon"; const command_line::arg_descriptor arg_config_file = { "config-file" diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 777593320..4d58891b3 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -3006,20 +3006,44 @@ namespace cryptonote return true; } // Iterate over the cache, supplying the data in a more accessible format + res.total_burnt = res.total_staked = res.total_yield = res.yield_per_stake = 0; res.yield_data.clear(); for (const auto& entry: ybi_cache) { - // Skip this entry if out-of=range + + // Check for last entry + if (entry.first == height - 1) { + res.total_staked = entry.second.locked_coins_tally; + if (entry.second.locked_coins_tally > 0) { + boost::multiprecision::uint128_t yield_per_stake = entry.second.slippage_total_this_block; + yield_per_stake *= COIN; + yield_per_stake /= entry.second.locked_coins_tally; + res.yield_per_stake = yield_per_stake.convert_to(); + } + } + + // Skip this entry if out-of-range if (req.from_height > 0 and entry.first < req.from_height) continue; if (req.to_height > 0 and entry.first > req.to_height) continue; - // Clone the data into the response - COMMAND_RPC_GET_YIELD_INFO::yield_data_t yd; - yd.block_height = entry.second.block_height; - yd.slippage_total_this_block = entry.second.slippage_total_this_block; - yd.locked_coins_this_block = entry.second.locked_coins_this_block; - yd.locked_coins_tally = entry.second.locked_coins_tally; - yd.network_health_percentage = entry.second.network_health_percentage; - res.yield_data.push_back(yd); + // Do we need to include raw data? + if (req.include_raw_data) { + + // Clone the data into the response + COMMAND_RPC_GET_YIELD_INFO::yield_data_t yd; + yd.block_height = entry.second.block_height; + yd.slippage_total_this_block = entry.second.slippage_total_this_block; + yd.locked_coins_this_block = entry.second.locked_coins_this_block; + yd.locked_coins_tally = entry.second.locked_coins_tally; + yd.network_health_percentage = entry.second.network_health_percentage; + res.yield_data.push_back(yd); + } + + // Perform the aggregation + if (entry.second.locked_coins_tally == 0) { + res.total_burnt += entry.second.slippage_total_this_block; + } else { + res.total_yield += entry.second.slippage_total_this_block; + } } res.status = CORE_RPC_STATUS_OK; return true; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index a6584c5b1..6f119e949 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -1294,10 +1294,12 @@ namespace cryptonote struct request_t { + bool include_raw_data; uint64_t from_height; uint64_t to_height; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(include_raw_data, false) KV_SERIALIZE_OPT(from_height, (uint64_t)0) KV_SERIALIZE_OPT(to_height, (uint64_t)0) END_KV_SERIALIZE_MAP() @@ -1308,9 +1310,17 @@ namespace cryptonote struct response_t { std::string status; + uint64_t total_burnt; + uint64_t total_staked; + uint64_t total_yield; + uint64_t yield_per_stake; std::vector yield_data; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(status) + KV_SERIALIZE(total_burnt) + KV_SERIALIZE(total_staked) + KV_SERIALIZE(total_yield) + KV_SERIALIZE(yield_per_stake) KV_SERIALIZE(yield_data) END_KV_SERIALIZE_MAP() }; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index d34e06d1c..e8ee3e6c4 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -8411,17 +8411,33 @@ bool simple_wallet::yield_info(const std::vector &args) { return false; // Scan the entries we have received to gather the state (total yield over period captured) + uint64_t total_burnt = 0; uint64_t total_yield = 0; + uint64_t yield_per_stake = 0; for (size_t idx=1; idx 0) { + boost::multiprecision::uint128_t yield_per_stake_128 = ybi_data.back().slippage_total_this_block; + yield_per_stake_128 *= COIN; + yield_per_stake_128 /= ybi_data.back().locked_coins_tally; + yield_per_stake = yield_per_stake_128.convert_to(); + } + // Output the necessary information about yield stats - message_writer(console_color_default, false) << boost::format(tr("YIELD INFO:\n\tTotal SAL supply: %d\n\tTotal coins locked: %d\n\tYield accrued over last %s: %d")) + message_writer(console_color_default, false) << boost::format(tr("YIELD INFO:\n\tTotal SAL supply: %d\n\tTotal coins burnt: %d\n\tTotal coins locked: %d\n\tYield accrued over last %s: %d\n\tYield per SAL staked: %d")) % print_money(total_supply_128.convert_to()) + % print_money(total_burnt) % print_money(ybi_data.back().locked_coins_tally) % get_human_readable_timespan((ybi_data.size()-1) * DIFFICULTY_TARGET_V2) - % print_money(total_yield); + % print_money(total_yield) + % print_money(yield_per_stake); // Now summarise our own YIELD TXs that are yet to amture tools::wallet2::transfer_container transfers; diff --git a/src/version.cpp.in b/src/version.cpp.in index 6dae3f2c4..5f278e08c 100644 --- a/src/version.cpp.in +++ b/src/version.cpp.in @@ -1,5 +1,5 @@ #define DEF_SALVIUM_VERSION_TAG "7f6b8da" -#define DEF_SALVIUM_VERSION "0.2.8" +#define DEF_SALVIUM_VERSION "0.3.0" #define DEF_MONERO_VERSION_TAG "@VERSIONTAG@" #define DEF_MONERO_VERSION "0.18.3.3" #define DEF_MONERO_RELEASE_NAME "Zero" diff --git a/src/wallet/message_store.cpp b/src/wallet/message_store.cpp index cf1d91d5a..db2538ffb 100644 --- a/src/wallet/message_store.cpp +++ b/src/wallet/message_store.cpp @@ -487,7 +487,7 @@ bool message_store::get_signer_index_by_monero_address(const cryptonote::account return true; } } - MWARNING("No authorized signer with Monero address " << account_address_to_string(monero_address)); + MWARNING("No authorized signer with Salvium address " << account_address_to_string(monero_address)); return false; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 218f62bba..b007709df 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2349,6 +2349,7 @@ bool wallet2::get_yield_info(std::vector& ybi_data cryptonote::COMMAND_RPC_GET_YIELD_INFO::request req = AUTO_VAL_INIT(req); cryptonote::COMMAND_RPC_GET_YIELD_INFO::response res = AUTO_VAL_INIT(res); m_daemon_rpc_mutex.lock(); + req.include_raw_data = true; bool r = invoke_http_json_rpc("/json_rpc", "get_yield_info", req, res, rpc_timeout); m_daemon_rpc_mutex.unlock(); if (r && res.status == CORE_RPC_STATUS_OK) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index b87501272..598ef0df7 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -914,7 +914,7 @@ namespace tools } if (addresses.empty()) { - er.message = std::string("No Monero address found at ") + url; + er.message = std::string("No Salvium address found at ") + url; return {}; } return addresses[0]; @@ -2223,7 +2223,7 @@ namespace tools } if (addresses.empty()) { - er.message = std::string("No Monero address found at ") + url; + er.message = std::string("No Salvium address found at ") + url; return {}; } return addresses[0]; @@ -3041,7 +3041,7 @@ namespace tools } if (addresses.empty()) { - er.message = std::string("No Monero address found at ") + url; + er.message = std::string("No Salvium address found at ") + url; return {}; } return addresses[0]; @@ -3095,7 +3095,7 @@ namespace tools } if (addresses.empty()) { - er.message = std::string("No Monero address found at ") + url; + er.message = std::string("No Salvium address found at ") + url; return {}; } return addresses[0]; @@ -4403,7 +4403,7 @@ namespace tools } if (addresses.empty()) { - er.message = std::string("No Monero address found at ") + url; + er.message = std::string("No Salvium address found at ") + url; return {}; } address = addresses[0];