Interim checkin
This code contains working "return address" semantics for CONVERT and YIELD.
This commit is contained in:
@@ -459,12 +459,9 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
|
||||
if (seedhash != crypto::null_hash)
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
}
|
||||
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
|
||||
if (seedhash != crypto::null_hash)
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
|
||||
// Preload the yield_block_info cache
|
||||
uint64_t yield_lock_period = get_config(m_nettype).YIELD_LOCK_PERIOD;
|
||||
@@ -593,11 +590,8 @@ void Blockchain::pop_blocks(uint64_t nblocks)
|
||||
if (stop_batch)
|
||||
m_db->batch_stop();
|
||||
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
}
|
||||
const crypto::hash seedhash = get_block_id_by_height(crypto::rx_seedheight(m_db->height()));
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
// This function tells BlockchainDB to remove the top block from the
|
||||
@@ -634,6 +628,9 @@ block Blockchain::pop_block_from_blockchain()
|
||||
throw;
|
||||
}
|
||||
|
||||
// Rebuild the YBI cache
|
||||
rebuild_ybi_cache();
|
||||
|
||||
// make sure the hard fork object updates its current version
|
||||
m_hardfork->on_block_popped(1);
|
||||
|
||||
@@ -1292,8 +1289,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<block_extended_info>
|
||||
}
|
||||
}
|
||||
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
|
||||
MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
|
||||
return true;
|
||||
@@ -1576,6 +1572,22 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Now consider the payouts from matured YIELD transactions
|
||||
|
||||
// Get the data for the block that matured this time
|
||||
cryptonote::yield_block_info ybi_matured;
|
||||
uint64_t start_height = height - get_config(m_nettype).YIELD_LOCK_PERIOD;
|
||||
bool ok = get_ybi_entry(start_height - 1, ybi_matured);
|
||||
if (ok && ybi_matured.locked_coins_this_block > 0) {
|
||||
|
||||
// Iterate over the cached data for block yield, calculating the yield payouts due
|
||||
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
|
||||
if (!calculate_yield_payouts(start_height, yield_payouts)) {
|
||||
LOG_ERROR("Failed to obtain yield payout information - aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1729,12 +1741,10 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
CHECK_AND_ASSERT_MES(get_block_by_hash(*from_block, prev_block), false, "From block not found"); // TODO
|
||||
uint64_t from_block_height = cryptonote::get_block_height(prev_block);
|
||||
height = from_block_height + 1;
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1791,12 +1801,10 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
median_weight = m_current_block_cumul_weight_limit / 2;
|
||||
diffic = get_difficulty_for_next_block();
|
||||
already_generated_coins = m_db->get_block_already_generated_coins(height - 1);
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
|
||||
uint64_t next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
b.timestamp = time(NULL);
|
||||
|
||||
@@ -1854,42 +1862,43 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
entry.return_address = meta.return_address;
|
||||
entry.type = meta.tx_type;
|
||||
entry.P_change = meta.one_time_public_key;
|
||||
entry.input_k_image = meta.input_k_image;
|
||||
entry.return_pubkey = meta.return_pubkey;
|
||||
protocol_entries.push_back(entry);
|
||||
}
|
||||
|
||||
// Get the YIELD TX information for matured staked coins
|
||||
// Check to see if there are any matured YIELD TXs
|
||||
uint64_t yield_lock_period = get_config(m_nettype).YIELD_LOCK_PERIOD;
|
||||
uint64_t start_height = height - yield_lock_period - 1;
|
||||
std::vector<cryptonote::yield_tx_info> yield_entries;
|
||||
int yield_tx_result = m_db->get_yield_tx_info(start_height, yield_entries);
|
||||
if (yield_entries.size()) {
|
||||
|
||||
// Get the YBI information for the 21,600 blocks that the matured TX(s), we can calculate yield
|
||||
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
|
||||
for (const auto& entry: yield_entries) {
|
||||
yield_payouts.emplace_back(std::make_pair(entry, 0));
|
||||
}
|
||||
|
||||
// Make sure the cache is fully populated and up to date
|
||||
if (!validate_ybi_cache()) {
|
||||
LOG_PRINT_L1("yield information cache is invalid - rebuilding cache");
|
||||
if (!rebuild_ybi_cache()) {
|
||||
LOG_ERROR("Failed to rebuild yield information cache - aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t start_height = height - yield_lock_period;
|
||||
cryptonote::yield_block_info ybi_matured;
|
||||
bool ok = get_ybi_entry(start_height - 1, ybi_matured);
|
||||
if (ok && ybi_matured.locked_coins_this_block > 0) {
|
||||
|
||||
// Iterate over the cached data for block yield, calculating the yield payouts due
|
||||
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
|
||||
if (!calculate_yield_payouts(start_height, yield_payouts)) {
|
||||
LOG_ERROR("Failed to obtain yield payout information - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the protocol_metadata entries here
|
||||
for (const auto& yield_entry: yield_payouts) {
|
||||
cryptonote::protocol_data_entry entry;
|
||||
entry.amount_burnt = yield_entry.second;
|
||||
entry.amount_minted = 0;
|
||||
entry.amount_slippage_limit = 0;
|
||||
entry.source_asset = "FULM";
|
||||
entry.destination_asset = "FULM";
|
||||
entry.return_address = yield_entry.first.return_address;
|
||||
entry.type = cryptonote::transaction_type::YIELD;
|
||||
entry.P_change = yield_entry.first.P_change;
|
||||
entry.return_pubkey = yield_entry.first.return_pubkey;
|
||||
protocol_entries.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Time to construct the protocol_tx
|
||||
uint64_t protocol_fee = 0;
|
||||
bool ok = construct_protocol_tx(height, protocol_fee, b.protocol_tx, protocol_entries, circ_supply, pr, b.major_version);
|
||||
ok = construct_protocol_tx(height, protocol_fee, b.protocol_tx, protocol_entries, circ_supply, pr, b.major_version);
|
||||
CHECK_AND_ASSERT_MES(ok, false, "Failed to construct protocol tx");
|
||||
|
||||
pool_cookie = m_tx_pool.cookie();
|
||||
@@ -2027,12 +2036,9 @@ bool Blockchain::get_miner_data(uint8_t& major_version, uint64_t& height, crypto
|
||||
major_version = m_hardfork->get_ideal_version(height);
|
||||
|
||||
seed_hash = crypto::null_hash;
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
{
|
||||
uint64_t seed_height, next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
}
|
||||
uint64_t seed_height, next_height;
|
||||
crypto::rx_seedheights(height, &seed_height, &next_height);
|
||||
seed_hash = get_block_id_by_height(seed_height);
|
||||
|
||||
difficulty = get_difficulty_for_next_block();
|
||||
median_weight = m_current_block_cumul_weight_median;
|
||||
@@ -2203,30 +2209,25 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
||||
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
|
||||
crypto::hash proof_of_work;
|
||||
memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data));
|
||||
if (b.major_version >= RX_BLOCK_VERSION)
|
||||
|
||||
crypto::hash seedhash = null_hash;
|
||||
uint64_t seedheight = rx_seedheight(bei.height);
|
||||
// seedblock is on the alt chain somewhere
|
||||
if (alt_chain.size() && alt_chain.front().height <= seedheight)
|
||||
{
|
||||
crypto::hash seedhash = null_hash;
|
||||
uint64_t seedheight = rx_seedheight(bei.height);
|
||||
// seedblock is on the alt chain somewhere
|
||||
if (alt_chain.size() && alt_chain.front().height <= seedheight)
|
||||
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
|
||||
{
|
||||
for (auto it=alt_chain.begin(); it != alt_chain.end(); it++)
|
||||
if (it->height == seedheight+1)
|
||||
{
|
||||
if (it->height == seedheight+1)
|
||||
{
|
||||
seedhash = it->bl.prev_id;
|
||||
break;
|
||||
}
|
||||
seedhash = it->bl.prev_id;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
seedhash = get_block_id_by_height(seedheight);
|
||||
}
|
||||
get_altblock_longhash(bei.bl, proof_of_work, seedhash);
|
||||
} else
|
||||
{
|
||||
get_block_longhash(this, bei.bl, proof_of_work, bei.height, 0);
|
||||
seedhash = get_block_id_by_height(seedheight);
|
||||
}
|
||||
get_altblock_longhash(bei.bl, proof_of_work, seedhash);
|
||||
if(!check_hash(proof_of_work, current_diff))
|
||||
{
|
||||
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
|
||||
@@ -4272,6 +4273,25 @@ bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vecto
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
||||
// Clear the yield payout amounts
|
||||
yield_container.empty();
|
||||
|
||||
// Get the YIELD TX information for matured staked coins
|
||||
std::vector<cryptonote::yield_tx_info> yield_entries;
|
||||
// We get the yield_tx_info from the block _before_ they started to accrue yield
|
||||
int yield_tx_result = m_db->get_yield_tx_info(start_height - 1, yield_entries);
|
||||
if (!yield_entries.size()) {
|
||||
|
||||
// Report error and abort
|
||||
LOG_ERROR("calculate_yield_payouts() called, but no yield TXs found at height " << start_height << " - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the YBI information for the 21,600 blocks that the matured TX(s), we can calculate yield
|
||||
for (const auto& entry: yield_entries) {
|
||||
yield_container.emplace_back(std::make_pair(entry, entry.locked_coins));
|
||||
}
|
||||
|
||||
// Iterate over the cached yield_block_info data
|
||||
uint64_t yield_lock_period = cryptonote::get_config(m_nettype).YIELD_LOCK_PERIOD;
|
||||
for (uint64_t idx = start_height; idx < start_height + yield_lock_period; ++idx) {
|
||||
@@ -4281,19 +4301,21 @@ bool Blockchain::calculate_yield_payouts(const uint64_t start_height, std::vecto
|
||||
return false;
|
||||
}
|
||||
yield_block_info ybi = m_yield_block_info_cache[idx];
|
||||
boost::multiprecision::int128_t slippage_128 = ybi.slippage_total;
|
||||
if (ybi.slippage_total_this_block == 0) continue;
|
||||
|
||||
boost::multiprecision::int128_t slippage_128 = ybi.slippage_total_this_block;
|
||||
slippage_128 = (slippage_128 * 3) / 10;
|
||||
|
||||
// Get the total number of coins locked at this height
|
||||
boost::multiprecision::int128_t locked_total_128 = ybi.locked_coins_tally;
|
||||
|
||||
// Iterate over the yield_container, adding each proportion of the yield
|
||||
for (const auto& entry: yield_container) {
|
||||
for (auto& entry: yield_container) {
|
||||
|
||||
boost::multiprecision::int128_t locked_coins_128 = entry.first.locked_coins;
|
||||
boost::multiprecision::int128_t yield_128 = (slippage_128 * locked_coins_128) / locked_total_128;
|
||||
entry.second += yield_128.convert_to<uint64_t>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Return success to caller
|
||||
@@ -4355,16 +4377,41 @@ bool Blockchain::validate_ybi_cache()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_yield_block_info_cache.count(height - ybi_cache_expected_size - 1) == 0) {
|
||||
if (m_yield_block_info_cache.count(height - ybi_cache_expected_size) == 0) {
|
||||
// Missing the latest block - report error and bail out
|
||||
LOG_ERROR("Failed to locate YBI entry for height " << (height - ybi_cache_expected_size - 1) << " - aborting");
|
||||
LOG_ERROR("Failed to locate YBI entry for height " << (height - ybi_cache_expected_size) << " - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool Blockchain::get_ybi_entry(const uint64_t height, cryptonote::yield_block_info& ybi)
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
||||
// Clear the provided container
|
||||
std::memset(&ybi, 0, sizeof(struct cryptonote::yield_block_info));
|
||||
|
||||
// Make sure the cache is fully populated and up to date
|
||||
if (!validate_ybi_cache()) {
|
||||
LOG_PRINT_L1("yield information cache is invalid - rebuilding cache");
|
||||
if (!rebuild_ybi_cache()) {
|
||||
LOG_ERROR("Failed to rebuild yield information cache - aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if the height is in the cache
|
||||
if (m_yield_block_info_cache.count(height) == 0) {
|
||||
LOG_ERROR("Failed to locate yield block info for height " << height << " - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the specified entry
|
||||
ybi = m_yield_block_info_cache[height];
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
//TODO: revisit, has changed a bit on upstream
|
||||
bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b, uint64_t& median_ts) const
|
||||
@@ -4769,7 +4816,6 @@ leave:
|
||||
return_tx_to_pool(txs);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
TIME_MEASURE_FINISH(vmt);
|
||||
|
||||
TIME_MEASURE_START(gcs);
|
||||
@@ -4784,7 +4830,6 @@ leave:
|
||||
return_tx_to_pool(txs);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
TIME_MEASURE_FINISH(vpt);
|
||||
|
||||
size_t block_weight;
|
||||
@@ -4814,7 +4859,17 @@ leave:
|
||||
{
|
||||
uint64_t long_term_block_weight = get_next_long_term_block_weight(block_weight);
|
||||
cryptonote::blobdata bd = cryptonote::block_to_blob(bl);
|
||||
new_height = m_db->add_block(std::make_pair(std::move(bl), std::move(bd)), block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs, m_nettype);
|
||||
yield_block_info new_ybi;
|
||||
std::memset(&new_ybi, 0, sizeof(struct yield_block_info));
|
||||
new_height = m_db->add_block(std::make_pair(std::move(bl), std::move(bd)), block_weight, long_term_block_weight, cumulative_difficulty, already_generated_coins, txs, m_nettype, new_ybi);
|
||||
|
||||
// Update the YBI cache data
|
||||
uint64_t yield_lock_period = cryptonote::get_config(m_nettype).YIELD_LOCK_PERIOD;
|
||||
uint64_t ybi_cache_expected_size = std::min(new_height, yield_lock_period);
|
||||
if (m_yield_block_info_cache.count(new_height - yield_lock_period) != 0) {
|
||||
m_yield_block_info_cache.erase(new_height - yield_lock_period);
|
||||
}
|
||||
m_yield_block_info_cache[new_height] = new_ybi;
|
||||
}
|
||||
catch (const KEY_IMAGE_EXISTS& e)
|
||||
{
|
||||
@@ -4886,8 +4941,7 @@ leave:
|
||||
for (const auto& notifier: m_block_notifiers)
|
||||
notifier(new_height - 1, {std::addressof(bl), 1});
|
||||
|
||||
if (m_hardfork->get_current_version() >= RX_BLOCK_VERSION)
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
rx_set_main_seedhash(seedhash.data, tools::get_max_concurrency());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1153,6 +1153,17 @@ namespace cryptonote
|
||||
* @return TRUE if the payouts were calculated successfully, FALSE otherwise
|
||||
*/
|
||||
bool calculate_yield_payouts(const uint64_t start_height, std::vector<std::pair<yield_tx_info, uint64_t>>& yield_payouts);
|
||||
|
||||
/**
|
||||
* @brief get the YBI entry for a particular height from the cache
|
||||
*
|
||||
* Retrieve the YBI entry for the specified height from the local cache.
|
||||
* If the cache is out of date, the cache will (attempt to) be rebuilt
|
||||
* before the entry is obtained.
|
||||
*
|
||||
* @return TRUE if the entry was located and returned, FALSE otherwise
|
||||
*/
|
||||
bool get_ybi_entry(const uint64_t height, cryptonote::yield_block_info& ybi);
|
||||
|
||||
/**
|
||||
* (re)build the yield_block_info cache from the blockchain
|
||||
|
||||
@@ -151,29 +151,19 @@ namespace cryptonote
|
||||
rate = COIN;
|
||||
return true;
|
||||
}
|
||||
if (from_asset == "FULM") {
|
||||
// FULM as source
|
||||
if (to_asset not_eq "FUSD") {
|
||||
// Invalid conversion - abort
|
||||
LOG_ERROR("Invalid conversion (" << from_asset << "," << to_asset << ") - aborting");
|
||||
return false;
|
||||
}
|
||||
// Scale to FUSD
|
||||
rate = pr["FUSD"];
|
||||
} else if (from_asset == "FUSD") {
|
||||
// FUSD as source
|
||||
if (to_asset not_eq "FULM") {
|
||||
// Invalid conversion - abort
|
||||
LOG_ERROR("Invalid conversion (" << from_asset << "," << to_asset << ") - aborting");
|
||||
return false;
|
||||
}
|
||||
// Scale to FULM
|
||||
boost::multiprecision::uint128_t rate_128 = COIN;
|
||||
rate_128 *= COIN;
|
||||
rate_128 /= pr["FUSD"];
|
||||
rate = rate_128.convert_to<uint64_t>();
|
||||
rate -= (rate % 10000);
|
||||
if ((from_asset == "FULM" && to_asset != "FUSD") ||
|
||||
(from_asset == "FUSD" && to_asset != "FULM")) {
|
||||
// Invalid conversion - abort
|
||||
LOG_ERROR("Invalid conversion (" << from_asset << "," << to_asset << ") - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Scale to correct value
|
||||
boost::multiprecision::uint128_t rate_128 = COIN;
|
||||
rate_128 *= pr[from_asset];
|
||||
rate_128 /= pr[to_asset];
|
||||
rate = rate_128.convert_to<uint64_t>();
|
||||
rate -= (rate % 10000);
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------
|
||||
@@ -246,9 +236,6 @@ namespace cryptonote
|
||||
// Force the TX type to 2
|
||||
tx.version = 2;
|
||||
|
||||
// Clear the unlock_time
|
||||
tx.unlock_time = 0;
|
||||
|
||||
keypair txkey = keypair::generate(hw::get_device("default"));
|
||||
add_tx_pub_key_to_extra(tx, txkey.pub);
|
||||
if (!sort_tx_extra(tx.extra, tx.extra))
|
||||
@@ -275,7 +262,7 @@ namespace cryptonote
|
||||
continue;
|
||||
}
|
||||
// CONVERT TX
|
||||
|
||||
/*
|
||||
// Create a secret TX key (= s)
|
||||
crypto::secret_key s = keypair::generate(hw::get_device("default")).sec;
|
||||
//additional_tx_keys.push_back(s);
|
||||
@@ -309,6 +296,7 @@ namespace cryptonote
|
||||
r = crypto::derive_subaddress_public_key(out_eph_public_key, derivation_syF, output_index, P_change_verify);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating protocol_tx outs: failed sanity check calling derive_subaddress_public_key(" << out_eph_public_key << ", " << derivation_syF << ", " << key_y << ", " << P_change_verify << ")");
|
||||
CHECK_AND_ASSERT_MES(entry.P_change == P_change_verify, false, "while creating protocol_tx outs: failed sanity check (keys do not match)");
|
||||
*/
|
||||
/*
|
||||
LOG_ERROR("***************************************************************************************");
|
||||
LOG_ERROR("output_index : " << output_index);
|
||||
@@ -322,32 +310,52 @@ namespace cryptonote
|
||||
LOG_ERROR("P_change_ver : " << P_change_verify);
|
||||
LOG_ERROR("***************************************************************************************");
|
||||
*/
|
||||
// Now calculate the slippage, and decide if it is going to be converted or refunded
|
||||
uint64_t amount_slippage = 0, amount_minted = 0;
|
||||
bool ok = cryptonote::calculate_conversion(entry.source_asset, entry.destination_asset, entry.amount_burnt, entry.amount_slippage_limit, amount_minted, amount_slippage, circ_supply, pr, hf_version);
|
||||
if (!ok) {
|
||||
LOG_ERROR("failed to calculate slippage when trying to build protocol_tx");
|
||||
return false;
|
||||
}
|
||||
if (amount_minted == 0) {
|
||||
|
||||
// REFUND
|
||||
LOG_PRINT_L2("Conversion TX refunded - slippage too high");
|
||||
txin_gen_totals[entry.source_asset] += entry.amount_burnt;
|
||||
|
||||
if (entry.type == cryptonote::transaction_type::CONVERT) {
|
||||
|
||||
// Now calculate the slippage, and decide if it is going to be converted or refunded
|
||||
uint64_t amount_slippage = 0, amount_minted = 0;
|
||||
bool ok = cryptonote::calculate_conversion(entry.source_asset, entry.destination_asset, entry.amount_burnt, entry.amount_slippage_limit, amount_minted, amount_slippage, circ_supply, pr, hf_version);
|
||||
if (!ok) {
|
||||
LOG_ERROR("failed to calculate slippage when trying to build protocol_tx");
|
||||
return false;
|
||||
}
|
||||
if (amount_minted == 0) {
|
||||
|
||||
// REFUND
|
||||
LOG_PRINT_L2("Conversion TX refunded - slippage too high");
|
||||
txin_gen_totals[entry.source_asset] += entry.amount_burnt;
|
||||
|
||||
// Create the TX output for this refund
|
||||
tx_out out;
|
||||
//cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
|
||||
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, entry.return_address, false, crypto::view_tag{}, out);
|
||||
additional_tx_public_keys.push_back(entry.return_pubkey);
|
||||
tx.vout.push_back(out);
|
||||
} else {
|
||||
|
||||
// CONVERTED
|
||||
LOG_PRINT_L2("Conversion TX submitted - converted " << print_money(entry.amount_burnt) << " " << entry.source_asset << " to " << print_money(amount_minted) << " " << entry.destination_asset << "(slippage " << print_money(amount_slippage) << ")");
|
||||
txin_gen_totals[entry.destination_asset] += amount_minted;
|
||||
|
||||
// Create the TX output for this conversion
|
||||
tx_out out;
|
||||
//cryptonote::set_tx_out(amount_minted, entry.destination_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
|
||||
cryptonote::set_tx_out(amount_minted, entry.destination_asset, 0, entry.return_address, false, crypto::view_tag{}, out);
|
||||
additional_tx_public_keys.push_back(entry.return_pubkey);
|
||||
tx.vout.push_back(out);
|
||||
}
|
||||
} else if (entry.type == cryptonote::transaction_type::YIELD) {
|
||||
|
||||
// PAYOUT
|
||||
LOG_PRINT_L2("Yield TX payout submitted " << entry.amount_burnt << entry.source_asset);
|
||||
txin_gen_totals[entry.source_asset] += entry.amount_burnt;
|
||||
|
||||
// Create the TX output for this refund
|
||||
tx_out out;
|
||||
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
|
||||
tx.vout.push_back(out);
|
||||
} else {
|
||||
|
||||
// CONVERTED
|
||||
LOG_PRINT_L2("Conversion TX submitted - converted " << entry.amount_burnt << entry.source_asset << " to " << amount_minted << entry.destination_asset << "(slippage " << amount_slippage << ")");
|
||||
txin_gen_totals[entry.destination_asset] += amount_minted;
|
||||
|
||||
// Create the TX output for this conversion
|
||||
tx_out out;
|
||||
cryptonote::set_tx_out(amount_minted, entry.destination_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
|
||||
//cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, out_eph_public_key, false, crypto::view_tag{}, out);
|
||||
cryptonote::set_tx_out(entry.amount_burnt, entry.source_asset, 0, entry.return_address, false, crypto::view_tag{}, out);
|
||||
additional_tx_public_keys.push_back(entry.return_pubkey);
|
||||
tx.vout.push_back(out);
|
||||
}
|
||||
}
|
||||
@@ -355,8 +363,6 @@ namespace cryptonote
|
||||
// Add in all of the additional TX pubkeys we need to process the payments
|
||||
add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys);
|
||||
|
||||
// TODO: create the YIELD outputs
|
||||
|
||||
// Create the txin_gen now
|
||||
txin_gen in;
|
||||
in.height = height;
|
||||
@@ -436,8 +442,6 @@ namespace cryptonote
|
||||
|
||||
tx.version = 2;
|
||||
|
||||
//lock
|
||||
tx.unlock_time = 0;//height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
|
||||
tx.vin.push_back(in);
|
||||
|
||||
tx.invalidate_hashes();
|
||||
@@ -561,7 +565,8 @@ namespace cryptonote
|
||||
const cryptonote::account_keys &sender_account_keys, // needed to calculate pretty much anything
|
||||
const crypto::public_key &P_change, // one-time public key from CONVERT/YIELD change
|
||||
const crypto::public_key &txkey_pub, // public TX key from CONVERT/YIELD TX
|
||||
crypto::public_key& F, // OUTPUT
|
||||
crypto::public_key& F, // OUTPUT return address OTPK
|
||||
crypto::public_key& F_txkey_pub, // OUTPUT TX pub key
|
||||
hw::device& hwdev // hardware device to use (usually a software dev)
|
||||
) {
|
||||
|
||||
@@ -591,7 +596,7 @@ namespace cryptonote
|
||||
}
|
||||
*/
|
||||
|
||||
// Now generate the return address
|
||||
// Now generate the return address EC point
|
||||
// F = (y^-1).a.P_change
|
||||
|
||||
// First, we need to produce the multiplicative inverse of the scalar "y" (aka "y^-1")
|
||||
@@ -609,22 +614,49 @@ namespace cryptonote
|
||||
|
||||
// Sanity check that we can reverse the invert safely
|
||||
rct::key key_aP_change = rct::pk2rct(pk_aP_change);
|
||||
rct::key key_test = rct::scalarmultKey(key_aP_change, key_inv_y);
|
||||
rct::key key_verify = rct::scalarmultKey(key_test, key_y);
|
||||
rct::key key_F = rct::scalarmultKey(key_aP_change, key_inv_y);
|
||||
rct::key key_verify = rct::scalarmultKey(key_F, key_y);
|
||||
CHECK_AND_ASSERT_MES(key_verify == key_aP_change, false, "at get_return_address: failed to verify invert() function with smK() approach");
|
||||
F = rct::rct2pk(key_test);
|
||||
|
||||
/*
|
||||
// From this point forward, we are departing from the original "return address" scheme
|
||||
// Create a secret TX key (= s)
|
||||
crypto::secret_key s = keypair::generate(hw::get_device("default")).sec;
|
||||
|
||||
// Now add the correct TX public key (= sP_change)
|
||||
// This has to be done using smK() call because of g_k_d() performing a torsion clear
|
||||
F_txkey_pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(P_change), rct::sk2rct(s)));
|
||||
|
||||
// Calculate the actual return address, because the field we already have is actually the TX pubkey to use
|
||||
// return address = Hs(syF || i)G + P_change = Hs(saP_change || i)G + P_change
|
||||
// Generate the uniqueness for the input
|
||||
|
||||
crypto::public_key syF = rct::rct2pk(rct::scalarmultKey(rct::scalarmultKey(key_F, key_y), rct::sk2rct(s)));
|
||||
crypto::key_derivation derivation_syF = AUTO_VAL_INIT(derivation_syF);
|
||||
std::memcpy(derivation_syF.data, syF.data, sizeof(crypto::key_derivation));
|
||||
|
||||
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
|
||||
r = crypto::derive_public_key(derivation_syF, uniqueness, P_change, out_eph_public_key);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating protocol_tx outs: failed to derive_public_key(" << derivation_syF << ", " << key_y << ", "<< P_change << ")");
|
||||
|
||||
// Sanity checks
|
||||
crypto::public_key P_change_verify = crypto::null_pkey;
|
||||
r = crypto::derive_subaddress_public_key(out_eph_public_key, derivation_syF, uniqueness, P_change_verify);
|
||||
CHECK_AND_ASSERT_MES(r, false, "while creating protocol_tx outs: failed sanity check calling derive_subaddress_public_key(" << out_eph_public_key << ", " << derivation_syF << ", " << key_y << ", " << P_change_verify << ")");
|
||||
CHECK_AND_ASSERT_MES(P_change == P_change_verify, false, "while creating protocol_tx outs: failed sanity check (keys do not match)");
|
||||
|
||||
// All is well - copy the return address
|
||||
F = out_eph_public_key;
|
||||
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
LOG_ERROR("uniqueness: " << uniqueness.data);
|
||||
//LOG_ERROR("uniqueness: " << uniqueness.data);
|
||||
LOG_ERROR("txkey_pub : " << txkey_pub);
|
||||
LOG_ERROR("a : " << sender_account_keys.m_view_secret_key);
|
||||
LOG_ERROR("s : " << s);
|
||||
LOG_ERROR("y : " << key_y);
|
||||
LOG_ERROR("P_change : " << P_change);
|
||||
LOG_ERROR("aP_change : " << pk_aP_change);
|
||||
LOG_ERROR("F : " << F);
|
||||
LOG_ERROR("*****************************************************************************");
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -695,7 +727,6 @@ namespace cryptonote
|
||||
} else {
|
||||
tx.version = 2;
|
||||
}
|
||||
tx.unlock_time = 0;//unlock_time;
|
||||
|
||||
tx.extra = extra;
|
||||
crypto::public_key txkey_pub;
|
||||
@@ -929,6 +960,8 @@ namespace cryptonote
|
||||
summary_outs_money += dst_entr.amount;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(additional_tx_public_keys.size() == additional_tx_keys.size(), false, "Internal error creating additional public keys");
|
||||
|
||||
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_additional_pub_keys));
|
||||
|
||||
// Is this a CONVERT tx?
|
||||
if (tx_type == cryptonote::transaction_type::CONVERT) {
|
||||
@@ -946,9 +979,9 @@ namespace cryptonote
|
||||
CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(tx.vout[0], P_change), false, "Internal error - failed to get TX change output public key");
|
||||
CHECK_AND_ASSERT_MES(P_change != crypto::null_pkey, false, "Internal error - not found TX change output for CONVERT tx");
|
||||
|
||||
// Now generate the return address
|
||||
CHECK_AND_ASSERT_MES(get_return_address(tx.version, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, hwdev), false, "Failed to get protocol destination address");
|
||||
|
||||
// Now generate the return address and TX pubkey
|
||||
CHECK_AND_ASSERT_MES(get_return_address(tx.version, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, tx.return_pubkey, hwdev), false, "Failed to get protocol destination address");
|
||||
|
||||
} else if (tx_type == cryptonote::transaction_type::YIELD) {
|
||||
|
||||
// Get the uniqueness for this TX - must be output zero we are interested in for a CONVERT or YIELD TX
|
||||
@@ -964,13 +997,12 @@ namespace cryptonote
|
||||
CHECK_AND_ASSERT_MES(cryptonote::get_output_public_key(tx.vout[0], P_change), false, "Internal error - failed to get TX change output public key");
|
||||
CHECK_AND_ASSERT_MES(P_change != crypto::null_pkey, false, "Internal error - not found TX change output for YIELD tx");
|
||||
|
||||
// Now generate the return address
|
||||
CHECK_AND_ASSERT_MES(get_return_address(tx.version, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, hwdev), false, "Failed to get protocol destination address");
|
||||
// Now generate the return address and TX pubkey
|
||||
CHECK_AND_ASSERT_MES(get_return_address(tx.version, uniqueness, sender_account_keys, P_change, txkey_pub, tx.return_address, tx.return_pubkey, hwdev), false, "Failed to get protocol destination address");
|
||||
}
|
||||
|
||||
remove_field_from_tx_extra(tx.extra, typeid(tx_extra_additional_pub_keys));
|
||||
|
||||
LOG_PRINT_L2("tx pubkey: " << txkey_pub);
|
||||
LOG_PRINT_L2("return tx pubkey: " << tx.return_pubkey);
|
||||
if (need_additional_txkeys)
|
||||
{
|
||||
LOG_PRINT_L2("additional tx pubkeys: ");
|
||||
@@ -1285,22 +1317,16 @@ namespace cryptonote
|
||||
epee::string_tools::hex_to_pod(longhash_202612, res);
|
||||
return true;
|
||||
}
|
||||
if (major_version >= RX_BLOCK_VERSION)
|
||||
crypto::hash hash;
|
||||
if (pbc != NULL)
|
||||
{
|
||||
crypto::hash hash;
|
||||
if (pbc != NULL)
|
||||
{
|
||||
const uint64_t seed_height = rx_seedheight(height);
|
||||
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
|
||||
} else
|
||||
{
|
||||
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
|
||||
}
|
||||
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
|
||||
} else {
|
||||
const int pow_variant = major_version >= 7 ? major_version - 6 : 0;
|
||||
crypto::cn_slow_hash(bd.data(), bd.size(), res, pow_variant, height);
|
||||
const uint64_t seed_height = rx_seedheight(height);
|
||||
hash = seed_hash ? *seed_hash : pbc->get_pending_block_id_by_height(seed_height);
|
||||
} else
|
||||
{
|
||||
memset(&hash, 0, sizeof(hash)); // only happens when generating genesis block
|
||||
}
|
||||
rx_slow_hash(hash.data, bd.data(), bd.size(), res.data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace cryptonote
|
||||
std::string destination_asset;
|
||||
uint8_t type;
|
||||
crypto::public_key P_change;
|
||||
crypto::key_image input_k_image;
|
||||
crypto::public_key return_pubkey;
|
||||
};
|
||||
|
||||
bool construct_protocol_tx(const size_t height, uint64_t& protocol_fee, transaction& tx, std::vector<protocol_data_entry>& protocol_data, std::map<std::string, uint64_t> circ_supply, const oracle::pricing_record& pr, const uint8_t hf_version);
|
||||
|
||||
@@ -379,7 +379,7 @@ namespace cryptonote
|
||||
if (!ok)
|
||||
return false;
|
||||
meta.one_time_public_key = change_output_public_key;
|
||||
meta.input_k_image = boost::get<cryptonote::txin_to_key>(tx.vin[0]).k_image;
|
||||
meta.return_pubkey = tx.return_pubkey;
|
||||
|
||||
if (!insert_key_images(tx, id, tx_relay))
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user