Interim checkin

This code contains working "return address" semantics for CONVERT and YIELD.
This commit is contained in:
Some Random Crypto Guy
2024-02-16 11:02:11 +00:00
parent a3a7f686f3
commit 606580a173
24 changed files with 457 additions and 281 deletions
+134 -80
View File
@@ -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;
}
+11
View File
@@ -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
+109 -83
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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;