diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 3de937ae0..404cf4e9f 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -232,17 +232,22 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair { // miner v2 txes have their coinbase output in one single out to save space, // and we store them as rct outputs with an identity mask + uint64_t unlock_time = 0; + if (!cryptonote::get_output_unlock_time(tx.vout[i], unlock_time)) { + LOG_PRINT_L1("Failed to get output unlock time, aborting transaction addition"); + throw std::runtime_error("Unexpected error getting output unlock_time, aborting"); + } if (miner_tx && tx.version == 2) { cryptonote::tx_out vout = tx.vout[i]; rct::key commitment = rct::zeroCommit(vout.amount); vout.amount = 0; - amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time, + amount_output_indices[i] = add_output(tx_hash, vout, i, unlock_time, &commitment); } else { - amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time, + amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, unlock_time, tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL); } } @@ -263,6 +268,7 @@ uint64_t BlockchainDB::add_block( const std::pair& blck , const uint64_t& coins_generated , const std::vector>& txs , const cryptonote::network_type& nettype + , cryptonote::yield_block_info& ybi ) { const block &blk = blck.first; @@ -378,7 +384,7 @@ uint64_t BlockchainDB::add_block( const std::pair& blck // No price available - bail out, because block is invalid throw std::runtime_error("Asset type '" + tally.first + "' is not present in available pricing record"); } - // Convert the amount into FULM + // Convert the FUSD amount into FULM boost::multiprecision::int128_t tally_128 = tally.second; tally_128 *= asset_price; tally_128 /= fulm_price; @@ -395,7 +401,7 @@ uint64_t BlockchainDB::add_block( const std::pair& blck // call out to subclass implementation to add the block & metadata time1 = epee::misc_utils::get_tick_count(); - add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, nettype); + add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, nettype, ybi); TIME_MEASURE_FINISH(time1); time_add_block1 += time1; diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index d9896fd78..29dd3aa38 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -157,7 +157,7 @@ struct txpool_tx_meta_t { crypto::hash max_used_block_id; crypto::hash last_failed_id; - crypto::key_image input_k_image; + crypto::public_key return_pubkey; crypto::public_key return_address; crypto::public_key one_time_public_key; uint64_t weight; @@ -199,8 +199,8 @@ struct txpool_tx_meta_t typedef struct yield_block_info { uint64_t block_height; - uint64_t slippage_total; - uint64_t locked_coins; + uint64_t slippage_total_this_block; + uint64_t locked_coins_this_block; uint64_t locked_coins_tally; uint8_t network_health_percentage; } yield_block_info; @@ -210,6 +210,8 @@ typedef struct yield_tx_info { crypto::hash tx_hash; uint64_t locked_coins; crypto::public_key return_address; + crypto::public_key P_change; + crypto::public_key return_pubkey; } yield_tx_info; #define DBF_SAFE 1 @@ -435,7 +437,8 @@ private: const crypto::hash& blk_hash, uint64_t slippage_total, uint64_t yield_total, - const cryptonote::network_type& nettype + const cryptonote::network_type& nettype, + cryptonote::yield_block_info& ybi ) = 0; /** @@ -889,7 +892,8 @@ public: , const uint64_t& coins_generated , const std::vector>& txs , const cryptonote::network_type& nettype - ); + , cryptonote::yield_block_info& ybi + ); /** * @brief checks if a block exists diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index c0a4dc276..d38b2c5e4 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -257,8 +257,8 @@ const char* const LMDB_CIRC_SUPPLY_TALLY = "circ_supply_tally"; /** * We have the following information that will go into a "yield_txs" table in the blockchain: * - * block_height (uint64_t) (this is the key field) - * --------------------------------------------------------- + * block_height (uint64_t) (this is the key field) + * ------------------------------------------------------------ * txn_hash (crypto:hash) (so we can verify) * dest_address (crypto::key) (where to send the yield) * amount_locked (uint64_t) (how much was locked) @@ -266,7 +266,7 @@ const char* const LMDB_CIRC_SUPPLY_TALLY = "circ_supply_tally"; * We also have the following information that will go into a "yield_blocks" table: * * block_height (uint64_t) (this is the key field) - * -------------------------------------------------------- + * ------------------------------------------------------------ * slippage_amount (uint64_t) (amount needed to determine yield payout for the block) * locked_coins (uint64_t) (total number of coins locked at this height) * locked_coins_total (uint64_t) (total number of coins locked at this height) @@ -804,13 +804,14 @@ int BlockchainLMDB::get_yield_block_info(const uint64_t height, yield_block_info { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); - mdb_txn_cursors *m_cursors = &m_wcursors; // Clear the YBI, just in case std::memset(&ybi, 0, sizeof(struct yield_block_info)); // Query for the matured YIELD_BLOCK_INFO information - CURSOR(yield_blocks) + TXN_PREFIX_RDONLY(); + RCURSOR(yield_blocks); + MDB_val v; MDB_val_set(k, height); int ret = mdb_cursor_get(m_cur_yield_blocks, &k, &v, MDB_SET); @@ -832,19 +833,21 @@ int BlockchainLMDB::get_yield_tx_info(const uint64_t height, std::vector= yield_lock_period) { + if (m_height > yield_lock_period) { uint64_t height_matured = m_height - yield_lock_period - 1; result = get_yield_block_info(height_matured, ybi_matured); if (result) @@ -919,8 +922,8 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l // Create the YIELD_BLOCK_INFO instance for this block ybi.block_height = m_height; - ybi.slippage_total = slippage_total; - ybi.locked_coins = yield_total; + ybi.slippage_total_this_block = slippage_total; + ybi.locked_coins_this_block = yield_total; ybi.locked_coins_tally = ybi_prev.locked_coins_tally - ybi_matured.locked_coins_tally + yield_total; ybi.network_health_percentage = 100; @@ -996,6 +999,7 @@ void BlockchainLMDB::remove_block() CURSOR(block_heights) CURSOR(blocks) CURSOR(circ_supply_tally) + CURSOR(yield_blocks) MDB_val_copy k(m_height - 1); MDB_val h = k; if ((result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &h, MDB_GET_BOTH))) @@ -1016,6 +1020,13 @@ void BlockchainLMDB::remove_block() if ((result = mdb_cursor_del(m_cur_block_info, 0))) throw1(DB_ERROR(lmdb_error("Failed to add removal of block info to db transaction: ", result).c_str())); + + MDB_val_copy k2(m_height - 1); + MDB_val v = k2; + if ((result = mdb_cursor_get(m_cur_yield_blocks, &k2, NULL, MDB_SET))) + throw1(BLOCK_DNE(lmdb_error("Attempting to remove yield block info that's not in the db: ", result).c_str())); + if ((result = mdb_cursor_del(m_cur_yield_blocks, 0))) + throw1(DB_ERROR(lmdb_error("Failed to add removal of yield block info to db transaction: ", result).c_str())); } boost::multiprecision::int128_t @@ -1229,6 +1240,15 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons yield_data.tx_hash = tx_hash; yield_data.return_address = tx.return_address; yield_data.locked_coins = tx.amount_burnt; + if (tx.vin.empty()) + throw0(DB_ERROR("tx.vin is empty (needed to create yield data for the PROTOCOL_TX)")); + if (tx.vin[0].type() != typeid(cryptonote::txin_to_key)) + throw0(DB_ERROR("tx.vin[0] is wrong type (needed to create yield data for the PROTOCOL_TX)")); + yield_data.return_pubkey = tx.return_pubkey; + if (tx.vout.size() != 1) + throw0(DB_ERROR("tx.vout is wrong size (needed to create yield data for the PROTOCOL_TX)")); + if (!cryptonote::get_output_public_key(tx.vout[0], yield_data.P_change)) + throw0(DB_ERROR("failed to get P_change from tx.vout[0] (needed to create yield data for the PROTOCOL_TX)")); MDB_val_set(val_height, m_height); MDB_val_set(val_yield_tx_data, yield_data); result = mdb_cursor_put(m_cur_yield_txs, &val_height, &val_yield_tx_data, MDB_APPEND); @@ -4606,7 +4626,7 @@ void BlockchainLMDB::block_rtxn_abort() const } uint64_t BlockchainLMDB::add_block(const std::pair& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, - const std::vector>& txs, const cryptonote::network_type& nettype) + const std::vector>& txs, const cryptonote::network_type& nettype, cryptonote::yield_block_info& ybi) { LOG_PRINT_L3("BlockchainLMDB::" << __func__); check_open(); @@ -4624,7 +4644,7 @@ uint64_t BlockchainLMDB::add_block(const std::pair& blk, size_t try { - BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, nettype); + BlockchainDB::add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, nettype, ybi); } catch (const DB_ERROR_TXN_START& e) { diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index dfb3aa9d2..77ec44dc1 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -342,6 +342,7 @@ public: , const uint64_t& coins_generated , const std::vector>& txs , const cryptonote::network_type& nettype + , cryptonote::yield_block_info& ybi ); virtual void set_batch_transactions(bool batch_transactions); @@ -399,7 +400,8 @@ private: const crypto::hash& blk_hash, uint64_t slippage_total, uint64_t yield_total, - const cryptonote::network_type& nettype + const cryptonote::network_type& nettype, + cryptonote::yield_block_info& ybi ); virtual void remove_block(); diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp index 6b6903a5b..e40ef3058 100644 --- a/src/blockchain_utilities/blockchain_import.cpp +++ b/src/blockchain_utilities/blockchain_import.cpp @@ -487,8 +487,9 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path try { + cryptonote::yield_block_info ybi; // This just gets discarded because we aren't looking to maintain a cache of YBI data in the import utility uint64_t long_term_block_weight = core.get_blockchain_storage().get_next_long_term_block_weight(block_weight); - core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET); + core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, ybi); } catch (const std::exception& e) { diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h index 68d33b575..4673e8490 100644 --- a/src/cryptonote_basic/cryptonote_basic.h +++ b/src/cryptonote_basic/cryptonote_basic.h @@ -199,8 +199,10 @@ namespace cryptonote std::vector extra; // TX type cryptonote::transaction_type type; - // Return address (encrypted) + // Return address crypto::public_key return_address; + // Return TX public key + crypto::public_key return_pubkey; // Source asset type std::string source_asset_type; // Destination asset type (this is only necessary for CONVERT transactions) @@ -213,13 +215,13 @@ namespace cryptonote BEGIN_SERIALIZE() VARINT_FIELD(version) if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false; - VARINT_FIELD(unlock_time) FIELD(vin) FIELD(vout) FIELD(extra) VARINT_FIELD(type) if (type != cryptonote::transaction_type::MINER && type != cryptonote::transaction_type::PROTOCOL) { FIELD(return_address) + FIELD(return_pubkey) FIELD(source_asset_type) FIELD(destination_asset_type) VARINT_FIELD(amount_burnt) @@ -238,6 +240,7 @@ namespace cryptonote extra.clear(); type = cryptonote::transaction_type::UNSET; return_address = crypto::null_pkey; + return_pubkey = crypto::null_pkey; source_asset_type.clear(); destination_asset_type.clear(); amount_burnt = 0; diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h index 663761b92..0ca761ef5 100644 --- a/src/cryptonote_basic/cryptonote_boost_serialization.h +++ b/src/cryptonote_basic/cryptonote_boost_serialization.h @@ -104,12 +104,16 @@ namespace boost inline void serialize(Archive &a, cryptonote::txout_to_key &x, const boost::serialization::version_type ver) { a & x.key; + a & x.asset_type; + a & x.unlock_time; } template inline void serialize(Archive &a, cryptonote::txout_to_tagged_key &x, const boost::serialization::version_type ver) { a & x.key; + a & x.asset_type; + a & x.unlock_time; a & x.view_tag; } @@ -162,13 +166,14 @@ namespace boost inline void serialize(Archive &a, cryptonote::transaction_prefix &x, const boost::serialization::version_type ver) { a & x.version; - a & x.unlock_time; + //a & x.unlock_time; a & x.vin; a & x.vout; a & x.extra; a & x.type; if (x.type != cryptonote::transaction_type::MINER && x.type != cryptonote::transaction_type::PROTOCOL) { a & x.return_address; + a & x.return_pubkey; a & x.source_asset_type; a & x.destination_asset_type; a & x.amount_burnt; @@ -180,13 +185,14 @@ namespace boost inline void serialize(Archive &a, cryptonote::transaction &x, const boost::serialization::version_type ver) { a & x.version; - a & x.unlock_time; + //a & x.unlock_time; a & x.vin; a & x.vout; a & x.extra; a & x.type; if (x.type != cryptonote::transaction_type::MINER && x.type != cryptonote::transaction_type::PROTOCOL) { a & x.return_address; + a & x.return_pubkey; a & x.source_asset_type; a & x.destination_asset_type; a & x.amount_burnt; diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index b57b88997..30be74017 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -391,7 +391,8 @@ namespace cryptonote */ // 1. Obtain P_change from the output (it is the subaddress public key) crypto::public_key P_change = crypto::null_pkey; - hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, P_change); + //hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, P_change); + hwdev.derive_subaddress_public_key(out_key, recv_derivation, origin_tx_data.uniqueness, P_change); // 2. Obtain a separate key_derivation for the _original_ P_change output // (using the TX public key from the CONVERT TX and the sender's private view key) @@ -408,7 +409,8 @@ namespace cryptonote CHECK_AND_ASSERT_MES(P_change == change_pk, false, "derived P_change public key does not match P_change"); // 5. Calculate the secret spend key "x_return" - CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, real_output_index, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'"); + //CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, real_output_index, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'"); + CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, origin_tx_data.uniqueness, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'"); in_ephemeral.sec = scalar_step1; CHECK_AND_ASSERT_MES(hwdev.secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive one-time output public key 'P_return'"); CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, @@ -1428,7 +1430,7 @@ namespace cryptonote CHECK_AND_ASSERT_MES(output_index < additional_derivations.size(), boost::none, "wrong number of additional derivations"); if (out_can_be_to_acc(view_tag_opt, additional_derivations[output_index], output_index, &hwdev)) { - CHECK_AND_ASSERT_MES(hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], output_index, subaddress_spendkey), boost::none, "Failed to derive subaddress public key"); + CHECK_AND_ASSERT_MES(hwdev.derive_subaddress_public_key(out_key, additional_derivations[output_index], uniqueness, subaddress_spendkey), boost::none, "Failed to derive subaddress public key"); auto found = subaddresses.find(subaddress_spendkey); if (found != subaddresses.end()) return subaddress_receive_info{ found->second, additional_derivations[output_index] }; diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 0cd8d9446..82dfc5ecc 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -259,11 +259,11 @@ namespace config 0x12 ,0x30, 0xF1, 0x71 , 0x61, 0x04 , 0x41, 0x61, 0x17, 0x31, 0x00, 0x82, 0x16, 0xA1, 0xA1, 0x10 } }; // Bender's nightmare - std::string const GENESIS_TX = "020001ff000180c09e90acbb140228a98ddaae317689e1deb19444b8d60a5132a1f249d8d0ce72b6eba6b79c22240446554c4d3c000000000000002101d52228aa3413ee1bfe2b10fbc1a8cbe2ef9ab2cea0c6bd338103e5f7546384290100"; + std::string const GENESIS_TX = "0201ff000180c09e90acbb14029f396e0265fb259de2dc3b8a956ad177f7432ad72034b1d0d28b1f54b59e64f90446554c4d3c000000000000002101901df6540da088783d037ac5b23f80d3adcbc10d171583480079097aadbe20dc0100"; uint32_t const GENESIS_NONCE = 10000; - const uint64_t YIELD_LOCK_PERIOD = 30*24*30; + const uint64_t YIELD_LOCK_PERIOD = 5;//30*24*30; // Hash domain separators const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof"; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index f27b6c0e5..4eff4efce 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -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 } } - 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> 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 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> 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> 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 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(); } - } // 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& 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; } diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 0c1394114..fae874c65 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -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>& 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 diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 5aeea0599..ca025bc0f 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -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(); - 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(); + 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; } diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index 52b344ead..462db65b4 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -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, std::map circ_supply, const oracle::pricing_record& pr, const uint8_t hf_version); diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index a44742d62..a323ec6d2 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -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(tx.vin[0]).k_image; + meta.return_pubkey = tx.return_pubkey; if (!insert_key_images(tx, id, tx_relay)) return false; diff --git a/src/multisig/multisig_tx_builder_ringct.cpp b/src/multisig/multisig_tx_builder_ringct.cpp index e96288078..fd443a4b7 100644 --- a/src/multisig/multisig_tx_builder_ringct.cpp +++ b/src/multisig/multisig_tx_builder_ringct.cpp @@ -866,7 +866,6 @@ bool tx_builder_ringct_t::init( // misc. fields unsigned_tx.version = 2; //rct = 2 - unsigned_tx.unlock_time = unlock_time; // sort inputs sort_sources(sources); diff --git a/src/oracle/pricing_record.cpp b/src/oracle/pricing_record.cpp index 5700c2317..6623e2456 100644 --- a/src/oracle/pricing_record.cpp +++ b/src/oracle/pricing_record.cpp @@ -202,13 +202,7 @@ namespace oracle { for (const auto& asset: assets) { if (asset.asset_type != asset_type) continue; - if (asset_type == "FULM") return asset.spot_price; - if (asset_type == "FUSD") { - boost::multiprecision::uint128_t exchange_128 = COIN; - exchange_128 *= COIN; - exchange_128 /= asset.spot_price; - return exchange_128.convert_to(); - } + return asset.spot_price; } return 0; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 2f02f05f1..ddf6290d5 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -1910,12 +1910,10 @@ namespace cryptonote crypto::hash seed_hash, next_seed_hash; if (!get_block_template(info.address, req.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, b, res.seed_height, seed_hash, next_seed_hash, error_resp)) return false; - if (b.major_version >= RX_BLOCK_VERSION) - { - res.seed_hash = string_tools::pod_to_hex(seed_hash); - if (seed_hash != next_seed_hash) - res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash); - } + + res.seed_hash = string_tools::pod_to_hex(seed_hash); + if (seed_hash != next_seed_hash) + res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash); res.reserved_offset = reserved_offset; store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64); @@ -2228,7 +2226,7 @@ namespace cryptonote } b.nonce = req.starting_nonce; crypto::hash seed_hash = crypto::null_hash; - if (b.major_version >= RX_BLOCK_VERSION && !epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash)) + if (!epee::string_tools::hex_to_pod(template_res.seed_hash, seed_hash)) { error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR; error_resp.message = "Error converting seed hash"; @@ -3458,12 +3456,10 @@ namespace cryptonote } res.hashing_blob = epee::string_tools::buff_to_hex_nodelimer(hashing_blob); res.top_hash = epee::string_tools::pod_to_hex(top_hash); - if (hashing_blob[0] >= RX_BLOCK_VERSION) - { - res.seed_hash = string_tools::pod_to_hex(seed_hash); - if (seed_hash != next_seed_hash) - res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash); - } + + res.seed_hash = string_tools::pod_to_hex(seed_hash); + if (seed_hash != next_seed_hash) + res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash); res.status = CORE_RPC_STATUS_OK; return true; diff --git a/src/rpc/rpc_payment.cpp b/src/rpc/rpc_payment.cpp index aca3e3761..d55da001c 100644 --- a/src/rpc/rpc_payment.cpp +++ b/src/rpc/rpc_payment.cpp @@ -234,16 +234,10 @@ namespace cryptonote block = is_current ? info.block : info.previous_block; *(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(nonce); - if (block.major_version >= RX_BLOCK_VERSION) - { - const crypto::hash &seed_hash = is_current ? info.seed_hash : info.previous_seed_hash; - crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data); - } - else - { - const int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0; - crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash, cn_variant, cryptonote::get_block_height(block)); - } + + const crypto::hash &seed_hash = is_current ? info.seed_hash : info.previous_seed_hash; + crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash.data); + if (!check_hash(hash, m_diff)) { MWARNING("Payment too low"); diff --git a/src/serialization/json_object.cpp b/src/serialization/json_object.cpp index 50ea6b8f8..46ffbc604 100644 --- a/src/serialization/json_object.cpp +++ b/src/serialization/json_object.cpp @@ -270,16 +270,18 @@ void toJsonValue(rapidjson::Writer& dest, const cryptonote::t dest.StartObject(); INSERT_INTO_JSON_OBJECT(dest, version, tx.version); - INSERT_INTO_JSON_OBJECT(dest, unlock_time, tx.unlock_time); INSERT_INTO_JSON_OBJECT(dest, inputs, tx.vin); INSERT_INTO_JSON_OBJECT(dest, outputs, tx.vout); INSERT_INTO_JSON_OBJECT(dest, extra, tx.extra); INSERT_INTO_JSON_OBJECT(dest, type, static_cast(tx.type)); - INSERT_INTO_JSON_OBJECT(dest, return_address, tx.return_address); - INSERT_INTO_JSON_OBJECT(dest, source_asset_type, tx.source_asset_type); - INSERT_INTO_JSON_OBJECT(dest, destination_asset_type, tx.destination_asset_type); - INSERT_INTO_JSON_OBJECT(dest, amount_burnt, tx.amount_burnt); - INSERT_INTO_JSON_OBJECT(dest, amount_slippage_limit, tx.amount_slippage_limit); + if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) { + INSERT_INTO_JSON_OBJECT(dest, return_address, tx.return_address); + INSERT_INTO_JSON_OBJECT(dest, return_pubkey, tx.return_pubkey); + INSERT_INTO_JSON_OBJECT(dest, source_asset_type, tx.source_asset_type); + INSERT_INTO_JSON_OBJECT(dest, destination_asset_type, tx.destination_asset_type); + INSERT_INTO_JSON_OBJECT(dest, amount_burnt, tx.amount_burnt); + INSERT_INTO_JSON_OBJECT(dest, amount_slippage_limit, tx.amount_slippage_limit); + } if (!tx.pruned) { INSERT_INTO_JSON_OBJECT(dest, signatures, tx.signatures); @@ -298,16 +300,18 @@ void fromJsonValue(const rapidjson::Value& val, cryptonote::transaction& tx) } GET_FROM_JSON_OBJECT(val, tx.version, version); - GET_FROM_JSON_OBJECT(val, tx.unlock_time, unlock_time); GET_FROM_JSON_OBJECT(val, tx.vin, inputs); GET_FROM_JSON_OBJECT(val, tx.vout, outputs); GET_FROM_JSON_OBJECT(val, tx.extra, extra); GET_FROM_JSON_OBJECT(val, tx.type, type); - GET_FROM_JSON_OBJECT(val, tx.return_address, return_address); - GET_FROM_JSON_OBJECT(val, tx.source_asset_type, source_asset_type); - GET_FROM_JSON_OBJECT(val, tx.destination_asset_type, destination_asset_type); - GET_FROM_JSON_OBJECT(val, tx.amount_burnt, amount_burnt); - GET_FROM_JSON_OBJECT(val, tx.amount_slippage_limit, amount_slippage_limit); + if (tx.type != cryptonote::transaction_type::MINER && tx.type != cryptonote::transaction_type::PROTOCOL) { + GET_FROM_JSON_OBJECT(val, tx.return_address, return_address); + GET_FROM_JSON_OBJECT(val, tx.return_pubkey, return_pubkey); + GET_FROM_JSON_OBJECT(val, tx.source_asset_type, source_asset_type); + GET_FROM_JSON_OBJECT(val, tx.destination_asset_type, destination_asset_type); + GET_FROM_JSON_OBJECT(val, tx.amount_burnt, amount_burnt); + GET_FROM_JSON_OBJECT(val, tx.amount_slippage_limit, amount_slippage_limit); + } GET_FROM_JSON_OBJECT(val, tx.rct_signatures, ringct); const auto& sigs = val.FindMember("signatures"); diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 5c6f0f6c5..0fd688b71 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -207,8 +207,9 @@ namespace const char* USAGE_SWEEP_ACCOUNT("sweep_account [index=[,,...] | index=all] [] [] [outputs=]
[]"); const char* USAGE_SWEEP_BELOW("sweep_below [index=[,,...]] [] []
[]"); const char* USAGE_SWEEP_SINGLE("sweep_single [] [] [outputs=]
[]"); + const char* USAGE_RETURN_PAYMENT("return_payment "); const char* USAGE_BURN("burn "); - const char* USAGE_CONVERT("convert "); + const char* USAGE_CONVERT("convert []"); const char* USAGE_LOCK_FOR_YIELD("lock_for_yield "); const char* USAGE_PRICE_INFO("price_info"); const char* USAGE_SUPPLY_INFO("supply_info"); @@ -3152,8 +3153,9 @@ bool simple_wallet::help(const std::vector &args/* = std::vector []\" - Send FULM or F$ to an address."); + message_writer() << tr("\"return_payment \" - Return a previously-received amount to sender."); message_writer() << tr("\"burn \" - destroy coins forever."); - message_writer() << tr("\"convert \" - convert between coin types."); + message_writer() << tr("\"convert []\" - convert between coin types."); message_writer() << tr("\"lock_for_yield \" - lock FULM in order to earn yield."); message_writer() << tr("\"price_info\" - Display current pricing information for supported assets."); message_writer() << tr("\"supply_info\" - Display circulating supply information."); @@ -3331,6 +3333,10 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::on_command, this, &simple_wallet::sweep_single, _1), tr(USAGE_SWEEP_SINGLE), tr("Send a single output of the given key image to an address without change.")); + m_cmd_binder.set_handler("return_payment", + boost::bind(&simple_wallet::return_payment, this, _1), + tr(USAGE_RETURN_PAYMENT), + tr("Returns the payment(s) received in TX to the original sender.")); m_cmd_binder.set_handler("burn", boost::bind(&simple_wallet::burn, this, _1), tr(USAGE_BURN), @@ -3338,7 +3344,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("convert", boost::bind(&simple_wallet::convert, this, _1), tr(USAGE_CONVERT), - tr("Converts into ")); + tr("Converts into , with optional ")); m_cmd_binder.set_handler("lock_for_yield", boost::bind(&simple_wallet::lock_for_yield, this, _1), tr(USAGE_LOCK_FOR_YIELD), @@ -7863,6 +7869,53 @@ bool simple_wallet::sweep_below(const std::vector &args_) return true; } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::return_payment(const std::vector &args_) +{ + // TODO: add locked versions + if (args_.size() != 1) + { + PRINT_USAGE(USAGE_RETURN_PAYMENT); + return true; + } + + std::vector local_args; + local_args.insert(local_args.end(), args_.begin(), args_.end()); + + // Get the TX hash we are interested in + crypto::hash txid; + if (!epee::string_tools::hex_to_pod(local_args[0], txid)) + { + fail_msg_writer() << tr("failed to parse txid"); + return true; + } + + // Get the TX details + tools::wallet2::transfer_container transfers; + m_wallet->get_transfers(transfers); + for (const auto& td: transfers) { + // Skip entries we don't care about + if (td.m_txid != txid) continue; + + // Found the specified entry - make sure we can return it + if (td.m_tx.type != cryptonote::transaction_type::TRANSFER) { + fail_msg_writer() << tr("incorrect TX type for txid ") << local_args[0]; + return true; + } + + // Verify we have a valid return_address and tx_pubkey + if (td.m_tx.return_address == crypto::null_pkey || td.m_tx.return_pubkey == crypto::null_pkey) { + fail_msg_writer() << tr("missing return_address/return_pubkey for txid ") << local_args[0]; + return true; + } + + // Create the destination address...somehow + //construct_tx_with_tx_key( + } + + fail_msg_writer() << tr("failed to locate txid ") << local_args[0]; + return true; +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::burn(const std::vector &args_) { // TODO: add locked versions diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index aa7250642..07a1d14eb 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -180,6 +180,7 @@ namespace cryptonote bool sweep_below(const std::vector &args); bool sweep_single(const std::vector &args); bool sweep_unmixable(const std::vector &args); + bool return_payment(const std::vector &args); bool burn(const std::vector &args); bool convert(const std::vector &args); bool lock_for_yield(const std::vector &args); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 17c469797..b46ea9229 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1871,9 +1871,10 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons crypto::public_key pk_change = crypto::null_pkey; bool ok = m_account.get_device().derive_subaddress_public_key(output_public_key, tx_scan_info.received->derivation, i, pk_change); THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to derive subaddress public key for CONVERT/YIELD TX"); - + // Find the TX public key for P_change - auto search = m_protocol_txs.find(pk_change); + //auto search = m_protocol_txs.find(pk_change); + auto search = m_protocol_txs.find(output_public_key); THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate protocol_tx entry to permit source usage"); size_t idx = search->second; THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate protocol_txs index in m_transfers"); @@ -2198,9 +2199,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote crypto::public_key pk_change = crypto::null_pkey; bool ok = m_account.get_device().derive_subaddress_public_key(output_public_key, additional_derivations[i], i, pk_change); THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to derive subaddress public key for CONVERT/YIELD TX"); - + // Find the TX public key for P_change - auto search = m_protocol_txs.find(pk_change); + //auto search = m_protocol_txs.find(pk_change); + auto search = m_protocol_txs.find(output_public_key); THROW_WALLET_EXCEPTION_IF(search == m_protocol_txs.end(), error::wallet_internal_error, "failed to locate protocol_tx entry to permit source usage"); size_t idx = search->second; THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate protocol_txs index in m_transfers"); @@ -2217,6 +2219,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(!cryptonote::calculate_uniqueness(td_origin.m_tx.type, k_image, td_origin.m_block_height, i, tx_scan_info[i].uniqueness), error::wallet_internal_error, "Failed to calculate uniqueness from origin TX"); + } else { // Get the uniqueness value @@ -2363,7 +2366,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(tx.vout[0], P_change), error::wallet_internal_error, "Failed to get change output public key"); //m_subaddresses[P_change] = {0x50524F54,0x4F434F4C}; /* {PROT,OCOL} - seemed like a good idea at the time, but harder to implement! */ m_subaddresses[P_change] = {0,0}; - m_protocol_txs.insert({P_change, m_transfers.size()-1}); + //m_protocol_txs.insert({P_change, m_transfers.size()-1}); + m_protocol_txs.insert({tx.return_address, m_transfers.size()-1}); if (tx.type == cryptonote::transaction_type::YIELD) { // Additionally, with YIELD TXs, we need to update our "balance staked" subtotal, because otherwise our balance is out by the staked coins until they mature! @@ -2466,7 +2470,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(!cryptonote::get_output_public_key(tx.vout[0], P_change), error::wallet_internal_error, "Failed to get change output public key"); //m_subaddresses[P_change] = {0x50524F54,0x4F434F4C}; m_subaddresses[P_change] = {0,0}; - m_protocol_txs.insert({P_change, m_transfers.size()-1}); + //m_protocol_txs.insert({P_change, m_transfers.size()-1}); + m_protocol_txs.insert({tx.return_address, m_transfers.size()-1}); } } } @@ -9123,8 +9128,8 @@ void wallet2::transfer_selected_rct(std::vector additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx); THROW_WALLET_EXCEPTION_IF(additional_tx_pub_keys.size() < td.m_internal_output_index, error::wallet_internal_error, "failed to obtain additional tx pub keys for PROTOCOL TX"); @@ -9260,7 +9265,8 @@ void wallet2::transfer_selected_rct(std::vectorsecond; THROW_WALLET_EXCEPTION_IF(idx >= get_num_transfer_details(), error::wallet_internal_error, "cannot locate m_protocol_txs index in m_transfers"); @@ -9789,8 +9795,8 @@ std::vector wallet2::create_transactions_2( uint32_t hf_version = get_current_hard_fork(); //const auto specific_transfers = m_transfers.at(source_asset); - oracle::pricing_record pricing_record; - std::vector> circ_amounts; + //oracle::pricing_record pricing_record; + //std::vector> circ_amounts; bool b = false; // Now perform all sanity checks specific to each tx type @@ -9804,10 +9810,10 @@ std::vector wallet2::create_transactions_2( case transaction_type::CONVERT: THROW_WALLET_EXCEPTION_IF(source_asset == dest_asset, error::wallet_internal_error, "Conversion TX must specify different source and destination asset types"); // Get the pricing record - b = get_pricing_record(pricing_record, current_height); - THROW_WALLET_EXCEPTION_IF(!b, error::wallet_internal_error, "Failed to get pricing record"); + //b = get_pricing_record(pricing_record, current_height); + //THROW_WALLET_EXCEPTION_IF(!b, error::wallet_internal_error, "Failed to get pricing record"); // Get the circulating supply data - THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply"); + //THROW_WALLET_EXCEPTION_IF(!get_circulating_supply(circ_amounts), error::wallet_internal_error, "Failed to get circulating supply"); break; case transaction_type::YIELD: THROW_WALLET_EXCEPTION_IF(dest_asset != "FULM", error::wallet_internal_error, "Yield TX must specify 'FULM' destination asset type"); @@ -10187,7 +10193,7 @@ std::vector wallet2::create_transactions_2( LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " outputs and " << tx.selected_transfers.size() << " inputs"); transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type, pricing_record); + test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type/*, pricing_record*/); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask); available_for_fee = test_ptx.fee + test_ptx.change_dts.amount + (!test_ptx.dust_added_to_fee ? test_ptx.dust : 0); @@ -10208,7 +10214,7 @@ std::vector wallet2::create_transactions_2( LOG_PRINT_L2("We made a tx, adjusting fee and saving it, we need " << print_money(needed_fee) << " and we have " << print_money(test_ptx.fee)); while (needed_fee > test_ptx.fee) { transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type, pricing_record); + test_tx, test_ptx, rct_config, use_view_tags, source_asset, dest_asset, tx_type/*, pricing_record*/); txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_quantization_mask); LOG_PRINT_L2("Made an attempt at a final " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(test_ptx.fee) << @@ -10282,8 +10288,8 @@ skip_tx: use_view_tags, /* const bool use_view_tags */ source_asset, dest_asset, - tx_type, - pricing_record); + tx_type/*, + pricing_record*/); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); tx.tx = test_tx; tx.ptx = test_ptx; @@ -10362,7 +10368,9 @@ bool wallet2::sanity_check(const std::vector &ptx_vector, s } catch (const std::exception &e) { received = 0; } - if (ptx.tx.type == cryptonote::transaction_type::CONVERT) + if (ptx.tx.type == cryptonote::transaction_type::BURN) + received += ptx.tx.amount_burnt; + else if (ptx.tx.type == cryptonote::transaction_type::CONVERT) received += ptx.tx.amount_burnt; else if (ptx.tx.type == cryptonote::transaction_type::YIELD) received += ptx.tx.amount_burnt; @@ -10593,7 +10601,7 @@ std::vector wallet2::create_transactions_from(const crypton tx.selected_transfers.size() << " outputs"); if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER, oracle::pricing_record()); + test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER/*, oracle::pricing_record()*/); else transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); @@ -10630,7 +10638,7 @@ std::vector wallet2::create_transactions_from(const crypton } if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra, - test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER, oracle::pricing_record()); + test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER/*, oracle::pricing_record()*/); else transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, outs, valid_public_keys_cache, unlock_time, needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); @@ -10669,7 +10677,7 @@ std::vector wallet2::create_transactions_from(const crypton pending_tx test_ptx; if (use_rct) { transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra, - test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER, oracle::pricing_record()); + test_tx, test_ptx, rct_config, use_view_tags, asset_type, asset_type, cryptonote::transaction_type::TRANSFER/*, oracle::pricing_record()*/); } else { transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, valid_public_keys_cache, unlock_time, tx.needed_fee, extra, detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx, use_view_tags); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index a006291fe..9bade0628 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1082,8 +1082,8 @@ private: const bool use_view_tags, const std::string& source_asset, const std::string& dest_asset, - const cryptonote::transaction_type& tx_type, - const oracle::pricing_record& pr); + const cryptonote::transaction_type& tx_type/*, + const oracle::pricing_record& pr*/); void commit_tx(pending_tx& ptx_vector); void commit_tx(std::vector& ptx_vector); diff --git a/src/wallet/wallet_rpc_payments.cpp b/src/wallet/wallet_rpc_payments.cpp index 06910ebbb..1a4123a50 100644 --- a/src/wallet/wallet_rpc_payments.cpp +++ b/src/wallet/wallet_rpc_payments.cpp @@ -153,15 +153,7 @@ bool wallet2::search_for_rpc_payment(uint64_t credits_target, uint32_t n_threads tpool.submit(&waiter, [&, i] { *(uint32_t*)(hashing_blob.data() + 39) = SWAP32LE(local_nonce-i); const uint8_t major_version = hashing_blob[0]; - if (major_version >= RX_BLOCK_VERSION) - { - crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data); - } - else - { - int cn_variant = hashing_blob[0] >= 7 ? hashing_blob[0] - 6 : 0; - crypto::cn_slow_hash(hashing_blob.data(), hashing_blob.size(), hash[i], cn_variant, height); - } + crypto::rx_slow_hash(seed_hash.data, hashing_blob.data(), hashing_blob.size(), hash[i].data); }); } waiter.wait();