Compare commits

...

6 Commits

Author SHA1 Message Date
Some Random Crypto Guy e69437ca6a added more secure verification of protocol_tx outputs; bumped version number 2024-06-07 17:02:13 +01:00
Neil Coggins 50075e04c3 fixed logging message for adding block to separate out the burnt reward from the block reward 2024-06-07 13:07:11 +01:00
Neil Coggins 7f3dba49a7 Merge branch 'rebase-v0.18.3.3' of https://github.com/somerandomcryptoguy/salvium into rebase-v0.18.3.3 2024-06-06 14:14:52 +01:00
Neil Coggins 9c098ae1fb added support for auto-frozen incoming payments 2024-06-06 14:13:14 +01:00
Some Random Crypto Guy 078fa00bc5 bumped version number 2024-06-05 15:54:06 +01:00
Some Random Crypto Guy 9dc1c429f7 replaced the windows fixes back into the rebased code 2024-06-05 15:52:35 +01:00
14 changed files with 219 additions and 82 deletions
+1 -1
View File
@@ -1 +1 @@
# Welcome to Fulmo
# Welcome to Salvium
@@ -36,6 +36,7 @@
#include "warnings.h"
#include "misc_log_ex.h"
#include <boost/numeric/conversion/bounds.hpp>
#include <boost/lexical_cast.hpp>
#include <typeinfo>
#include <iomanip>
+21 -2
View File
@@ -847,7 +847,7 @@ int BlockchainLMDB::get_yield_tx_info(const uint64_t height, std::vector<yield_t
while (1)
{
int ret = mdb_cursor_get(m_cur_yield_txs, &k, &v, op);
op = MDB_NEXT;
op = MDB_NEXT_DUP;
if (ret == MDB_NOTFOUND)
break;
if (ret)
@@ -1249,9 +1249,28 @@ uint64_t BlockchainLMDB::add_transaction_data(const crypto::hash& blk_hash, cons
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)"));
// Because LMDB is shockingly bad at handling duplicates, we have resorted to using a counter of elements
// in the first element of the struct.
MDB_val data;
MDB_val_set(val_height, m_height);
result = mdb_cursor_get(m_cur_yield_txs, &val_height, &data, MDB_SET);
if (!result)
{
mdb_size_t num_elems = 0;
result = mdb_cursor_count(m_cur_yield_txs, &num_elems);
if (result)
throw0(DB_ERROR(std::string("Failed to get number of yield TXs for height: ").append(mdb_strerror(result)).c_str()));
yield_data.block_height = num_elems;
}
else if (result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("Failed to get output amount in db transaction: ", result).c_str()));
else
yield_data.block_height = 0;
// Now we know how many there are, write out the data to the DB
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);
result = mdb_cursor_put(m_cur_yield_txs, &val_height, &val_yield_tx_data, MDB_APPENDDUP);
if (result)
throw0(DB_ERROR( lmdb_error("Failed to add tx yield data to db transaction: ", result).c_str() ));
}
+2 -1
View File
@@ -110,7 +110,8 @@ namespace tools
catch(...)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//boost::filesystem::copy_file(file_path, file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(file_path, file_path + ".unportable");
data_file.close();
data_file.open( file_path, std::ios_base::binary | std::ios_base::in);
if(data_file.fail())
+18
View File
@@ -115,6 +115,24 @@ static int flock_exnb(int fd)
namespace tools
{
void copy_file(const std::string& from, const std::string& to)
{
using boost::filesystem::path;
#if BOOST_VERSION < 107400
// Remove this preprocessor if/else when we are bumping the boost version.
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_option::overwrite_if_exists);
#else
boost::filesystem::copy_file(
path(from),
path(to),
boost::filesystem::copy_options::overwrite_existing);
#endif
}
std::function<void(int)> signal_handler::m_handler;
private_file::private_file() noexcept : m_handle(), m_filename() {}
+2
View File
@@ -67,6 +67,8 @@ namespace tools
}
};
void copy_file(const std::string& from, const std::string& to);
//! A file restricted to process owner AND process. Deletes file on destruction.
class private_file {
std::unique_ptr<std::FILE, close_file> m_handle;
@@ -399,8 +399,12 @@ namespace cryptonote
// SRCG: This is a confusing one - for some reason I was using the line below, and it _seemed_ to work...
// ... but I think it was luck! the "od.output_index" would only work for the TD_ORIGIN data, of course...
//hwdev.derive_subaddress_public_key(out_key, recv_derivation, od.output_index, P_change);
hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, P_change);
if (od.tx_type == cryptonote::transaction_type::CONVERT || od.tx_type == cryptonote::transaction_type::STAKE) {
hwdev.derive_subaddress_public_key(out_key, recv_derivation, 0, P_change);
} else {
hwdev.derive_subaddress_public_key(out_key, recv_derivation, real_output_index, 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)
crypto::key_derivation derivation_P_change_tx = AUTO_VAL_INIT(derivation_P_change_tx);
@@ -416,9 +420,11 @@ 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"
// SRCG: And another confusing one - luck again?!?!?
// CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, od.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'");
if (od.tx_type == cryptonote::transaction_type::CONVERT || od.tx_type == cryptonote::transaction_type::STAKE) {
CHECK_AND_ASSERT_MES(hwdev.derive_secret_key(recv_derivation, 0, sk_spend, scalar_step1), false, "Failed to derive one-time output secret key 'x_return'");
} else {
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'");
}
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,
+105 -61
View File
@@ -1491,15 +1491,6 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
return true;
}
key_images_container keys;
uint64_t fee_summary = 0;
uint64_t t_checktx = 0;
uint64_t t_exists = 0;
uint64_t t_pool = 0;
uint64_t t_dblspnd = 0;
uint64_t n_pruned = 0;
// Build a map of outputs from the protocol_tx
std::map<crypto::public_key, std::tuple<std::string, uint64_t, uint64_t>> outputs;
for (auto& o : b.protocol_tx.vout) {
@@ -1514,6 +1505,9 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
return false;
}
}
// Maintain a count of outputs that we have verified
std::vector<crypto::public_key> outputs_verified;
size_t tx_index = 0;
// Iterate over the block's transaction hashes, grabbing each
@@ -1530,69 +1524,119 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
return false;
}
// Check to see if the TX is a conversion or not
if (tx->type != cryptonote::transaction_type::CONVERT) {
// Only conversion (and failed conversion, aka refund) TXs need to be verified - skip this TX
continue;
}
/*
// Verify that the TX has an output in the protocol_tx to verify
if (outputs.count(tx->return_address) != 1) {
LOG_ERROR("Failed to locate output for conversion TX id " << tx->hash << " - rejecting block");
return false;
}
if (hf_version >= HF_VERSION_ENABLE_CONVERT) {
// Check to see if the TX is a conversion or not
if (tx->type != cryptonote::transaction_type::CONVERT) {
// Only conversion (and failed conversion, aka refund) TXs need to be verified - skip this TX
continue;
}
// Get the output information
std::string output_asset_type;
uint64_t output_amount;
uint64_t output_unlock_time;
std::tie(output_asset_type, output_amount, output_unlock_time) = outputs[tx->return_address];
// Verify the asset_type
if (tx->source_asset_type == output_asset_type) {
// Check the amount for REFUND
if (tx->amount_burnt != output_amount) {
LOG_ERROR("Output amount does not match amount_burnt for refunded TX id " << tx->hash << " - rejecting block");
// Verify that the TX has an output in the protocol_tx to verify
if (outputs.count(tx->return_address) != 1) {
LOG_ERROR("Block at height: " << height << " - Failed to locate output for conversion TX id " << tx->hash << " - rejecting block");
return false;
}
} else if (tx->destination_asset_type == output_asset_type) {
// Check the amount for CONVERT
// Verify the amount of the conversion
uint64_t amount_minted_check = 0, amount_slippage_check = 0;
bool ok = cryptonote::calculate_conversion(tx->source_asset_type, tx->destination_asset_type, tx->amount_burnt, tx->amount_slippage_limit, amount_minted_check, amount_slippage_check, circ_supply, b.pricing_record, hf_version);
if (!ok) {
LOG_ERROR("Failed to calculate conversion for TX id " << tx->hash << " - rejecting block");
// Get the output information
std::string output_asset_type;
uint64_t output_amount;
uint64_t output_unlock_time;
std::tie(output_asset_type, output_amount, output_unlock_time) = outputs[tx->return_address];
// Verify the asset_type
if (tx->source_asset_type == output_asset_type) {
// Check the amount for REFUND
if (tx->amount_burnt != output_amount) {
LOG_ERROR("Block at height: " << height << " - Output amount does not match amount_burnt for refunded TX id " << tx->hash << " - rejecting block");
return false;
}
// Verified the refund successfully
outputs_verified.push_back(tx->return_address);
} else if (tx->destination_asset_type == output_asset_type) {
// Check the amount for CONVERT
// Verify the amount of the conversion
uint64_t amount_minted_check = 0, amount_slippage_check = 0;
bool ok = cryptonote::calculate_conversion(tx->source_asset_type, tx->destination_asset_type, tx->amount_burnt, tx->amount_slippage_limit, amount_minted_check, amount_slippage_check, circ_supply, b.pricing_record, hf_version);
if (!ok) {
LOG_ERROR("Block at height: " << height << " - Failed to calculate conversion for TX id " << tx->hash << " - rejecting block");
return false;
}
if (amount_minted_check != output_amount) {
LOG_ERROR("Block at height: " << height << " - Output amount does not match amount_burnt for refunded TX id " << tx->hash << " - rejecting block");
return false;
}
// Verified the conversion successfully
outputs_verified.push_back(tx->return_address);
} else {
LOG_ERROR("Block at height: " << height << " - Output asset type incorrect: source " << tx->source_asset_type << ", dest " << tx->destination_asset_type << ", got " << output_asset_type << " - rejecting block");
return false;
}
if (amount_minted_check != output_amount) {
LOG_ERROR("Output amount does not match amount_burnt for refunded TX id " << tx->hash << " - rejecting block");
return false;
}
} else {
LOG_ERROR("Output asset type incorrect: source " << tx->source_asset_type << ", dest " << tx->destination_asset_type << ", got " << output_asset_type << " - rejecting block");
return false;
}
*/
}
// Now consider the payouts from matured YIELD transactions
// Get the data for the block that matured this time
cryptonote::yield_block_info ybi_matured;
// Can we have matured STAKE transactions yet?
uint64_t lock_period = get_config(m_nettype).STAKE_LOCK_PERIOD;
uint64_t start_height = (height > lock_period) ? height - lock_period - 1 : 0;
bool ok = get_ybi_entry(start_height, ybi_matured);
if (ok && ybi_matured.locked_coins_this_block > 0) {
// Iterate over the cached data for block yield, calculating the yield payouts due
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
if (!calculate_yield_payouts(start_height, yield_payouts)) {
LOG_ERROR("Failed to obtain yield payout information - aborting");
return false;
if (height > lock_period) {
// Yes - Get the staking data for the block that matured this time
cryptonote::yield_block_info ybi_matured;
uint64_t matured_height = height - lock_period - 1;
bool ok = get_ybi_entry(matured_height, ybi_matured);
if (ok && ybi_matured.locked_coins_this_block > 0) {
// Iterate over the cached data for block yield, calculating the yield payouts due
std::vector<std::pair<yield_tx_info, uint64_t>> yield_payouts;
if (!calculate_yield_payouts(matured_height, yield_payouts)) {
LOG_ERROR("Block at height: " << height << " - Failed to obtain yield payout information - aborting");
return false;
}
// Iterate the yield payouts, verifying as we go
for (const auto& payout: yield_payouts) {
// Do we have a singular matching output in tx.vout?
if (outputs.count(payout.first.return_address) != 1) {
LOG_ERROR("Block at height: " << height << " - Failed to locate output for matured TX id " << payout.first.tx_hash << " - rejecting block");
return false;
}
// Get the output information
std::string output_asset_type;
uint64_t output_amount;
uint64_t output_unlock_time;
std::tie(output_asset_type, output_amount, output_unlock_time) = outputs[payout.first.return_address];
// Verify the asset type - must be SAL
if (output_asset_type != "SAL") {
LOG_ERROR("Block at height: " << height << " - Incorrect output asset type for matured TX id " << payout.first.tx_hash << " - rejecting block");
return false;
}
// Verify the amount
if (output_amount != payout.second) {
LOG_ERROR("Block at height: " << height << " - Incorrect output amount for matured TX id " << payout.first.tx_hash << " - rejecting block");
return false;
}
// Amount and return_address match our expectation
outputs_verified.push_back(payout.first.return_address);
}
}
}
// All candidates have been evaluated - make sure there are no other outputs that have not been catered for
if (outputs.size() != outputs_verified.size()) {
LOG_ERROR("Block at height: " << height << " - Incorrect number of outputs - expected " << outputs_verified.size() << " but received " << outputs.size() << " - rejecting block");
return false;
}
// Everything checks out
return true;
}
//------------------------------------------------------------------
@@ -4944,7 +4988,7 @@ leave:
return false;
}
MINFO("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_weight: " << coinbase_weight << ", cumulative weight: " << cumulative_block_weight << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
MINFO("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward - bl.miner_tx.amount_burnt) << "(" << print_money(base_reward - bl.miner_tx.amount_burnt) << " reward + " << print_money(fee_summary) << " fees), coinbase_weight: " << coinbase_weight << ", cumulative weight: " << cumulative_block_weight << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
if(m_show_time_stats)
{
MINFO("Height: " << new_height << " coinbase weight: " << coinbase_weight << " cumm: "
+3 -2
View File
@@ -42,7 +42,7 @@
#include <boost/serialization/version.hpp>
#include "net_peerlist_boost_serialization.h"
#include "common/util.h"
namespace nodetool
{
@@ -200,7 +200,8 @@ namespace nodetool
if (!out)
{
// if failed, try reading in unportable mode
boost::filesystem::copy_file(path, path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//boost::filesystem::copy_file(path, path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
tools::copy_file(path, path + ".unportable");
src_file.close();
src_file.open( path , std::ios_base::binary | std::ios_base::in);
if(src_file.fail())
+24 -1
View File
@@ -3178,6 +3178,25 @@ bool simple_wallet::set_enable_multisig(const std::vector<std::string> &args/* =
return true;
}
bool simple_wallet::set_freeze_incoming_payments(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
if (args.size() < 2)
{
fail_msg_writer() << tr("Value not specified");
return true;
}
const auto pwd_container = get_and_verify_password();
if (pwd_container)
{
parse_bool_and_use(args[1], [&](bool r) {
m_wallet->freeze_incoming_payments(r);
m_wallet->rewrite(m_wallet_file, pwd_container->password());
});
}
return true;
}
bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
if(args.empty())
@@ -3533,7 +3552,9 @@ simple_wallet::simple_wallet()
"enable-multisig-experimental <1|0>\n "
" Set this to allow multisig commands. Multisig may currently be exploitable if parties do not trust each other.\n "
"inactivity-lock-timeout <unsigned int>\n "
" How many seconds to wait before locking the wallet (0 to disable)."));
" How many seconds to wait before locking the wallet (0 to disable).\n"
"freeze-incoming-payments <1|0>\n "
" Whether to have incoming payments automatically frozen, so they cannot be spent erroneously."));
m_cmd_binder.set_handler("encrypted_seed",
boost::bind(&simple_wallet::on_command, this, &simple_wallet::encrypted_seed, _1),
tr("Display the encrypted Electrum-style mnemonic seed."));
@@ -3948,6 +3969,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "credits-target = " << m_wallet->credits_target();
success_msg_writer() << "load-deprecated-formats = " << m_wallet->load_deprecated_formats();
success_msg_writer() << "enable-multisig-experimental = " << m_wallet->is_multisig_enabled();
success_msg_writer() << "freeze-incoming-payments = " << m_wallet->is_freeze_incoming_payments_enabled();
return true;
}
else
@@ -4015,6 +4037,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("auto-mine-for-rpc-payment-threshold", set_auto_mine_for_rpc_payment_threshold, tr("floating point >= 0"));
CHECK_SIMPLE_VARIABLE("credits-target", set_credits_target, tr("unsigned integer"));
CHECK_SIMPLE_VARIABLE("enable-multisig-experimental", set_enable_multisig, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("freeze-incoming-payments", set_freeze_incoming_payments, tr("0 or 1"));
}
fail_msg_writer() << tr("set: unrecognized argument(s)");
return true;
+1
View File
@@ -154,6 +154,7 @@ namespace cryptonote
bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>());
bool set_load_deprecated_formats(const std::vector<std::string> &args = std::vector<std::string>());
bool set_enable_multisig(const std::vector<std::string> &args = std::vector<std::string>());
bool set_freeze_incoming_payments(const std::vector<std::string> &args = std::vector<std::string>());
bool set_persistent_rpc_client_id(const std::vector<std::string> &args = std::vector<std::string>());
bool set_auto_mine_for_rpc_payment_threshold(const std::vector<std::string> &args = std::vector<std::string>());
bool set_credits_target(const std::vector<std::string> &args = std::vector<std::string>());
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_SALVIUM_VERSION_TAG "7f6b8da"
#define DEF_SALVIUM_VERSION "0.2.0"
#define DEF_SALVIUM_VERSION "0.2.3"
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "0.18.3.3"
#define DEF_MONERO_RELEASE_NAME "Zero"
+26 -8
View File
@@ -1240,6 +1240,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_load_deprecated_formats(false),
m_credits_target(0),
m_enable_multisig(false),
m_freeze_incoming_payments(false),
m_pool_info_query_time(0),
m_has_ever_refreshed_from_node(false),
m_allow_mismatched_daemon_version(false)
@@ -2178,9 +2179,15 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
// Calculate the subaddress public_key (P_change)
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/RETURN TX");
if (tx.type == cryptonote::transaction_type::PROTOCOL) {
// Force the output index to be 0 in all cases, despite where it appears in this TX
bool ok = m_account.get_device().derive_subaddress_public_key(output_public_key, tx_scan_info.received->derivation, 0, pk_change);
THROW_WALLET_EXCEPTION_IF(!ok, error::wallet_internal_error, "Failed to derive subaddress public key for CONVERT/YIELD TX");
} else {
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 RETURN TX");
}
// Flag to indicate this is a TX that uses a return_address
bool use_od = false;
cryptonote::origin_data od = AUTO_VAL_INIT(od);
@@ -2193,6 +2200,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
use_od = true;
od.tx_pub_key = get_tx_pub_key_from_extra(td_origin.m_tx);
od.output_index = td_origin.m_internal_output_index;
od.tx_type = td_origin.m_tx.type;
}
if (m_multisig)
@@ -2214,12 +2222,14 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
{
tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask, m_account.get_device());
}
/*
if (tx_scan_info.money_transfered == 0)
{
MERROR("Invalid output amount, skipping");
tx_scan_info.error = true;
return;
}
*/
outs.push_back(i);
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info.received->index][tx_scan_info.asset_type] >= std::numeric_limits<uint64_t>::max() - tx_scan_info.money_transfered,
error::wallet_internal_error, "Overflow in received amounts");
@@ -2642,7 +2652,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_mask = rct::identity();
td.m_rct = false;
}
td.m_frozen = false;
td.m_frozen = m_freeze_incoming_payments;
set_unspent(m_transfers.size()-1);
if (td.m_key_image_known)
m_key_images[td.m_key_image] = m_transfers.size()-1;
@@ -2992,7 +3002,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
if (tx.type == cryptonote::transaction_type::PROTOCOL) {
if (td_origin_idx != ((uint64_t)-1)) {
// Get the origin TD information
payment.m_amount = payment.m_amounts[0];
payment.m_amount = payment.m_amounts.empty() ? 0 : payment.m_amounts[0];
payment.m_tx_type = m_transfers[td_origin_idx].m_tx.type;
payment.m_fee = m_transfers[td_origin_idx].m_tx.amount_burnt;
} else {
@@ -4856,6 +4866,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
value2.SetInt(m_enable_multisig ? 1 : 0);
json.AddMember("enable_multisig", value2, json.GetAllocator());
value2.SetInt(m_freeze_incoming_payments ? 1 : 0);
json.AddMember("freeze_incoming_payments", value2, json.GetAllocator());
// Serialize the JSON object
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
@@ -5002,6 +5015,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
m_auto_mine_for_rpc_payment_threshold = -1.0f;
m_credits_target = 0;
m_enable_multisig = false;
m_freeze_incoming_payments = false;
m_allow_mismatched_daemon_version = false;
}
else if(json.IsObject())
@@ -5239,6 +5253,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
m_credits_target = field_credits_target;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, enable_multisig, int, Int, false, false);
m_enable_multisig = field_enable_multisig;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, freeze_incoming_payments, int, Int, false, false);
m_freeze_incoming_payments = field_freeze_incoming_payments;
}
else
{
@@ -6425,8 +6441,9 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
catch (...)
{
LOG_PRINT_L0("Failed to open portable binary, trying unportable");
if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
std::stringstream iss;
//if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
if (use_fs) tools::copy_file(m_wallet_file, m_wallet_file + ".unportable");
std::stringstream iss;
iss.str("");
iss << cache_data;
boost::archive::binary_iarchive ar(iss);
@@ -6447,7 +6464,8 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
catch (...)
{
LOG_PRINT_L0("Failed to open portable binary, trying unportable");
if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
//if (use_fs) boost::filesystem::copy_file(m_wallet_file, m_wallet_file + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
if (use_fs) tools::copy_file(m_wallet_file, m_wallet_file + ".unportable");
std::stringstream iss;
iss.str("");
iss << cache_file_buf;
+3
View File
@@ -1450,6 +1450,8 @@ private:
void credits_target(uint64_t threshold) { m_credits_target = threshold; }
bool is_multisig_enabled() const { return m_enable_multisig; }
void enable_multisig(bool enable) { m_enable_multisig = enable; }
bool is_freeze_incoming_payments_enabled() const { return m_freeze_incoming_payments; }
void freeze_incoming_payments(bool enable) { m_freeze_incoming_payments = enable; }
bool is_mismatched_daemon_version_allowed() const { return m_allow_mismatched_daemon_version; }
void allow_mismatched_daemon_version(bool allow_mismatch) { m_allow_mismatched_daemon_version = allow_mismatch; }
@@ -1991,6 +1993,7 @@ private:
rpc_payment_state_t m_rpc_payment_state;
uint64_t m_credits_target;
bool m_enable_multisig;
bool m_freeze_incoming_payments;
bool m_allow_mismatched_daemon_version;
// Aux transaction data from device