a number of fixes; disabled return_payment as the functionality is changing to NOT require returning the same output

This commit is contained in:
Some Random Crypto Guy
2024-03-27 14:50:31 +00:00
parent 606580a173
commit 7bafd2866c
5 changed files with 303 additions and 36 deletions
+13 -3
View File
@@ -264,6 +264,8 @@ namespace config
uint32_t const GENESIS_NONCE = 10000;
const uint64_t YIELD_LOCK_PERIOD = 5;//30*24*30;
std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A";
// Hash domain separators
const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof";
@@ -342,6 +344,8 @@ namespace config
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
"-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A";
}
namespace stagenet
@@ -366,6 +370,8 @@ namespace config
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5YBxWx1AZCA9jTUk8Pr2uZ9jpfRt\n"
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
"-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A";
}
}
@@ -393,6 +399,7 @@ namespace cryptonote
std::array<std::string, 3> const ORACLE_URLS;
std::string const ORACLE_PUBLIC_KEY;
uint64_t YIELD_LOCK_PERIOD;
std::string TREASURY_ADDRESS;
};
inline const config_t& get_config(network_type nettype)
{
@@ -408,7 +415,8 @@ namespace cryptonote
::config::GENESIS_NONCE,
::config::ORACLE_URLS,
::config::ORACLE_PUBLIC_KEY,
::config::YIELD_LOCK_PERIOD
::config::YIELD_LOCK_PERIOD,
::config::TREASURY_ADDRESS
};
static const config_t testnet = {
::config::testnet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX,
@@ -422,7 +430,8 @@ namespace cryptonote
::config::testnet::GENESIS_NONCE,
::config::testnet::ORACLE_URLS,
::config::testnet::ORACLE_PUBLIC_KEY,
::config::testnet::YIELD_LOCK_PERIOD
::config::testnet::YIELD_LOCK_PERIOD,
::config::testnet::TREASURY_ADDRESS
};
static const config_t stagenet = {
::config::stagenet::CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX,
@@ -436,7 +445,8 @@ namespace cryptonote
::config::stagenet::GENESIS_NONCE,
::config::stagenet::ORACLE_URLS,
::config::stagenet::ORACLE_PUBLIC_KEY,
::config::stagenet::YIELD_LOCK_PERIOD
::config::stagenet::YIELD_LOCK_PERIOD,
::config::stagenet::TREASURY_ADDRESS
};
switch (nettype)
{
+4 -1
View File
@@ -1898,7 +1898,10 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
// Time to construct the protocol_tx
uint64_t protocol_fee = 0;
ok = construct_protocol_tx(height, protocol_fee, b.protocol_tx, protocol_entries, circ_supply, pr, b.major_version);
address_parse_info treasury_address_info;
ok = cryptonote::get_account_address_from_str(treasury_address_info, m_nettype, get_config(m_nettype).TREASURY_ADDRESS);
CHECK_AND_ASSERT_MES(ok, false, "Failed to obtain treasury address info");
ok = construct_protocol_tx(height, protocol_fee, b.protocol_tx, protocol_entries, circ_supply, pr, miner_address, treasury_address_info.address, b.major_version);
CHECK_AND_ASSERT_MES(ok, false, "Failed to construct protocol tx");
pool_cookie = m_tx_pool.cookie();
+62 -14
View File
@@ -197,18 +197,12 @@ namespace cryptonote
// Apply slippage to the burnt amount
amount_slippage = amount_burnt >> 5; // (1/32)
if (hf_version >= HF_VERSION_SLIPPAGE_YIELD) {
// Apply slippage to the burnt amount
amount_slippage = amount_burnt >> 5; // (1/32)
// Check that the slippage is acceptable
if (amount_slippage > amount_slippage_limit) {
// Bail out with no conversion
LOG_PRINT_L1("Unable to convert - slippage limit was too low");
amount_minted = 0;
return true;
}
// Check that the slippage is acceptable
if (amount_slippage > amount_slippage_limit) {
// Bail out with no conversion
LOG_PRINT_L1("Unable to convert - slippage limit was too low");
amount_minted = 0;
return true;
}
// Work out the converted amount
@@ -224,11 +218,13 @@ namespace cryptonote
std::vector<protocol_data_entry>& protocol_data,
std::map<std::string, uint64_t> circ_supply,
const oracle::pricing_record& pr,
const account_public_address &miner_address,
const account_public_address &treasury_address,
const uint8_t hf_version) {
// A vector to contain all of the additional _tx_secret_keys_
//std::vector<crypto::secret_key>& additional_tx_keys;
// Clear the TX contents
tx.set_null();
tx.type = cryptonote::transaction_type::PROTOCOL;
@@ -255,6 +251,7 @@ namespace cryptonote
// Calculate the slippage for the output amounts
LOG_PRINT_L2("Creating protocol_tx...");
uint64_t slippage_total = 0;
std::vector<crypto::public_key> additional_tx_public_keys;
for (auto const& entry: protocol_data) {
if (entry.destination_asset == "BURN") {
@@ -337,6 +334,19 @@ namespace cryptonote
// 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;
// Add the slippage to our total for the block
if (entry.source_asset == "FULM") {
slippage_total += amount_slippage;
} else {
// Convert the slippage into a FULM amount so we can pay a proportion to the miner
uint64_t conversion_rate = 0, amount_slippage_converted = 0;
ok = get_conversion_rate(pr, entry.source_asset, entry.destination_asset, conversion_rate);
CHECK_AND_ASSERT_MES(ok, false, "Failed to get conversion rate for miner payout");
ok = get_converted_amount(conversion_rate, amount_slippage, amount_slippage_converted);
CHECK_AND_ASSERT_MES(ok, false, "Failed to get converted slippage amount for miner payout");
slippage_total += amount_slippage_converted;
}
// Create the TX output for this conversion
tx_out out;
@@ -359,9 +369,46 @@ namespace cryptonote
tx.vout.push_back(out);
}
}
// 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);
if (slippage_total > 0) {
// Add a payout for the miner
uint64_t slippage_miner = slippage_total / 5;
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);
crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
// Calculate the uniqueness
crypto::key_image k_image;
ec_scalar uniqueness;
CHECK_AND_ASSERT_MES(calculate_uniqueness(tx.type, k_image, height, ((size_t)-1), uniqueness), false, "while constructing miner_tx: failed to calculate uniqueness");
r = crypto::derive_public_key(derivation, uniqueness, miner_address.m_spend_public_key, out_eph_public_key);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
tx_out out_miner;
cryptonote::set_tx_out(slippage_miner, "FULM", 0, out_eph_public_key, false, crypto::view_tag{}, out_miner);
tx.vout.push_back(out_miner);
// Add a payout for the treasury
crypto::key_derivation derivation_treasury = AUTO_VAL_INIT(derivation_treasury);
crypto::public_key out_eph_public_key_treasury = AUTO_VAL_INIT(out_eph_public_key_treasury);
r = crypto::generate_key_derivation(treasury_address.m_view_public_key, txkey.sec, derivation_treasury);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << treasury_address.m_view_public_key << ", " << txkey.sec << ")");
r = crypto::derive_public_key(derivation_treasury, uniqueness, treasury_address.m_spend_public_key, out_eph_public_key_treasury);
CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << 0 << ", "<< miner_address.m_spend_public_key << ")");
uint64_t slippage_treasury = slippage_miner >> 1;
tx_out out_treasury;
cryptonote::set_tx_out(slippage_treasury, "FULM", 0, out_eph_public_key_treasury, false, crypto::view_tag{}, out_treasury);
tx.vout.push_back(out_treasury);
}
// Create the txin_gen now
txin_gen in;
@@ -930,6 +977,7 @@ namespace cryptonote
// Do not create outputs that are for the destination asset type - discard them as unused
if (dst_entr.asset_type == dest_asset) {
tx.amount_burnt += dst_entr.amount;
tx.amount_slippage_limit = dst_entr.slippage_limit;
continue;
}
} else if (tx_type == cryptonote::transaction_type::YIELD) {
+6 -4
View File
@@ -65,7 +65,7 @@ namespace cryptonote
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);
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 account_public_address &miner_address, const account_public_address &treasury_address, const uint8_t hf_version);
//---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
bool construct_protocol_tx(size_t height, transaction& tx, size_t max_outs = 999, uint8_t hard_fork_version = 1);
@@ -111,15 +111,16 @@ namespace cryptonote
{
std::string original;
uint64_t amount; //money
uint64_t slippage_limit; //percentage of slippage permitted
account_public_address addr; //destination address
std::string asset_type;
bool is_subaddress;
bool is_integrated;
bool is_change;
tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)), asset_type("FULM"), is_subaddress(false), is_integrated(false), is_change(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { }
tx_destination_entry() : amount(0), slippage_limit(0), addr(AUTO_VAL_INIT(addr)), asset_type("FULM"), is_subaddress(false), is_integrated(false), is_change(false) { }
tx_destination_entry(uint64_t a, const account_public_address &ad, bool is_subaddress) : amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false), is_change(false) { }
tx_destination_entry(const std::string &o, uint64_t a, const account_public_address &ad, bool is_subaddress) : original(o), amount(a), slippage_limit(0), addr(ad), is_subaddress(is_subaddress), is_integrated(false) { }
std::string address(network_type nettype, const crypto::hash &payment_id) const
{
@@ -139,6 +140,7 @@ namespace cryptonote
BEGIN_SERIALIZE_OBJECT()
FIELD(original)
VARINT_FIELD(amount)
VARINT_FIELD(slippage_limit)
FIELD(addr)
FIELD(asset_type)
FIELD(is_subaddress)
+218 -14
View File
@@ -6707,6 +6707,7 @@ bool simple_wallet::transfer_main(
vector<cryptonote::address_parse_info> dsts_info;
vector<cryptonote::tx_destination_entry> dsts;
double slippage_limit = 0.0;
for (size_t i = 0; i < local_args.size(); )
{
dsts_info.emplace_back();
@@ -6737,15 +6738,27 @@ bool simple_wallet::transfer_main(
}
else if (i + 1 < local_args.size())
{
r = cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[i], oa_prompter);
bool ok = cryptonote::parse_amount(de.amount, local_args[i + 1]);
if(!ok || 0 == de.amount)
{
fail_msg_writer() << tr("amount is wrong: ") << local_args[i] << ' ' << local_args[i + 1] <<
", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max());
return false;
if (transfer_type == Convert) {
bool ok = cryptonote::parse_amount(de.amount, local_args[i]);
if(!ok || 0 == de.amount)
{
fail_msg_writer() << tr("amount is wrong: ") << local_args[i] << ", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max());
return false;
}
double slippage_limit = std::stod(local_args[i+1]); // Already validated in simple_wallet::convert()
de.slippage_limit = ((uint64_t)((double)de.amount * slippage_limit)) / 100;
} else {
r = cryptonote::get_account_address_from_str_or_url(info, m_wallet->nettype(), local_args[i], oa_prompter);
bool ok = cryptonote::parse_amount(de.amount, local_args[i + 1]);
if(!ok || 0 == de.amount)
{
fail_msg_writer() << tr("amount is wrong: ") << local_args[i] << ' ' << local_args[i + 1] <<
", " << tr("expected number from 0 to ") << print_money(std::numeric_limits<uint64_t>::max());
return false;
}
de.original = local_args[i];
de.slippage_limit = 0;
}
de.original = local_args[i];
i += 2;
}
else
@@ -6759,6 +6772,7 @@ bool simple_wallet::transfer_main(
return false;
}
de.asset_type = source_asset;
de.slippage_limit = 0;
++i;
} else {
if (boost::starts_with(local_args[i], "fulmo:"))
@@ -7871,6 +7885,9 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::return_payment(const std::vector<std::string> &args_)
{
if (!try_connect_to_daemon())
return true;
// TODO: add locked versions
if (args_.size() != 1)
{
@@ -7891,11 +7908,13 @@ bool simple_wallet::return_payment(const std::vector<std::string> &args_)
// Get the TX details
tools::wallet2::transfer_container transfers;
crypto::key_image ki;
bool found_ki = false;
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];
@@ -7908,9 +7927,158 @@ bool simple_wallet::return_payment(const std::vector<std::string> &args_)
return true;
}
// Create the destination address...somehow
//construct_tx_with_tx_key(
// Check that we have the key image information, and that it is usable
if (!td.m_key_image_known || td.m_key_image_partial || td.m_spent || td.m_frozen) {
fail_msg_writer() << tr("key image is unavailable (partial / unknown / spent / frozen) for txid ") << local_args[0];
return true;
}
ki = td.m_key_image;
found_ki = true;
}
// Check we have a valid key_image
if (!found_ki) {
fail_msg_writer() << tr("key image is unavailable (partial / unknown / spent / frozen) for txid ") << local_args[0];
return true;
}
// This is nonsense, really - priority isn't really a problem for Fulmo
uint32_t priority = 0;
priority = m_wallet->adjust_priority(priority);
// This should be fixed by the protocol - any changes would stand out like a sore thumb
size_t fake_outs_count = m_wallet->get_min_ring_size() - 1;
uint64_t adjusted_fake_outs_count = m_wallet->adjust_mixin(fake_outs_count);
if (adjusted_fake_outs_count > fake_outs_count)
{
fail_msg_writer() << (boost::format(tr("ring size %u is too small, minimum is %u")) % (fake_outs_count+1) % (adjusted_fake_outs_count+1)).str();
return true;
}
if (adjusted_fake_outs_count < fake_outs_count)
{
fail_msg_writer() << (boost::format(tr("ring size %u is too large, maximum is %u")) % (fake_outs_count+1) % (adjusted_fake_outs_count+1)).str();
return true;
}
// We will only use one output - the one we are returning - to pay for the transaction fully
size_t outputs = 1;
std::vector<uint8_t> extra;
SCOPED_WALLET_UNLOCK();
/*
try
{
// figure out what tx will be necessary
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, outputs, fake_outs_count, 0, priority, extra);
if (ptx_vector.empty())
{
fail_msg_writer() << tr("No outputs found");
return true;
}
if (ptx_vector.size() > 1)
{
fail_msg_writer() << tr("Multiple transactions are created, which is not supposed to happen");
return true;
}
if (ptx_vector[0].selected_transfers.size() != 1)
{
fail_msg_writer() << tr("The transaction uses multiple or no inputs, which is not supposed to happen");
return true;
}
// give user total and fee, and prompt to confirm
uint64_t total_fee = ptx_vector[0].fee;
uint64_t total_sent = m_wallet->get_transfer_details(ptx_vector[0].selected_transfers.front()).amount();
std::ostringstream prompt;
if (!process_ring_members(ptx_vector, prompt, m_wallet->print_ring_members()))
return true;
prompt << boost::format(tr("Sweeping %s for a total fee of %s. Is this okay?")) %
print_money(total_sent) %
print_money(total_fee);
std::string accepted = input_line(prompt.str(), true);
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
{
fail_msg_writer() << tr("transaction cancelled.");
return true;
}
// actually commit the transactions
if (m_wallet->multisig())
{
CHECK_MULTISIG_ENABLED();
bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "multisig_monero_tx";
}
}
else if (m_wallet->get_account().get_device().has_tx_cold_sign())
{
try
{
tools::wallet2::signed_tx_set signed_tx;
std::vector<cryptonote::address_parse_info> dsts_info;
dsts_info.push_back(info);
if (!cold_sign_tx(ptx_vector, signed_tx, dsts_info, [&](const tools::wallet2::signed_tx_set &tx){ return accept_loaded_tx(tx); })){
fail_msg_writer() << tr("Failed to cold sign transaction with HW wallet");
return true;
}
commit_or_save(signed_tx.ptx, m_do_not_relay);
success_msg_writer(true) << tr("Money successfully sent, transaction: ") << get_transaction_hash(ptx_vector[0].tx);
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon());
}
catch (...)
{
LOG_ERROR("Unknown error");
fail_msg_writer() << tr("unknown error");
}
}
else if (m_wallet->watch_only())
{
bool r = m_wallet->save_tx(ptx_vector, "unsigned_monero_tx");
if (!r)
{
fail_msg_writer() << tr("Failed to write transaction(s) to file");
}
else
{
success_msg_writer(true) << tr("Unsigned transaction(s) successfully written to file: ") << "unsigned_monero_tx";
}
}
else
{
m_wallet->commit_tx(ptx_vector[0]);
success_msg_writer(true) << tr("Money successfully sent, transaction: ") << get_transaction_hash(ptx_vector[0].tx);
}
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_wallet->is_trusted_daemon());
}
catch (...)
{
LOG_ERROR("unknown error");
fail_msg_writer() << tr("unknown error");
}
*/
fail_msg_writer() << tr("return_payment() is not implemented");
return true;
fail_msg_writer() << tr("failed to locate txid ") << local_args[0];
return true;
@@ -7947,18 +8115,49 @@ bool simple_wallet::burn(const std::vector<std::string> &args_)
bool simple_wallet::convert(const std::vector<std::string> &args_)
{
// TODO: add locked versions
if (args_.size() != 3)
if (args_.size() not_eq 3 and args_.size() not_eq 4)
{
fail_msg_writer() << tr("missing / extraneous argument(s)");
PRINT_USAGE(USAGE_CONVERT);
return true;
}
std::vector<std::string> local_args = args_;
std::string strLastArg = local_args.back();
// Check to see if the last arg is "slippage_limit" (a decimal number)
double slippage_limit = 0.0;
if (args_.size() == 4) {
// Expect to be able to parse the last arg as a double
try
{
slippage_limit = std::stod(strLastArg);
if (slippage_limit < 0.0 or slippage_limit > 90.0) {
fail_msg_writer() << tr("invalid slippage_limit value : expected 0.0-90.0, got ") << slippage_limit;
PRINT_USAGE(USAGE_CONVERT);
return true;
}
// Update the last arg value
local_args.pop_back();
strLastArg = local_args.back();
}
catch (std::invalid_argument const& ex)
{
fail_msg_writer() << tr("invalid argument(s): ") << ex.what();
PRINT_USAGE(USAGE_CONVERT);
return true;
}
catch (std::out_of_range const& ex)
{
fail_msg_writer() << tr("out of range for slippage limit: ") << ex.what();
PRINT_USAGE(USAGE_CONVERT);
return true;
}
}
// Get the destination asset type
std::string source_asset, dest_asset;
std::string strLastArg = local_args.back();
std::transform(strLastArg.begin(), strLastArg.end(), strLastArg.begin(), ::toupper);
if (strLastArg not_eq "FULM" and strLastArg not_eq "FUSD") {
fail_msg_writer() << tr("invalid destination asset_type");
@@ -7984,6 +8183,11 @@ bool simple_wallet::convert(const std::vector<std::string> &args_)
PRINT_USAGE(USAGE_CONVERT);
return true;
}
// Check for slippage_limit again
if (slippage_limit != 0.0) {
local_args.push_back(std::to_string(slippage_limit));
}
transfer_main(Convert, source_asset, dest_asset, local_args, false);
return true;