Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 69480b79e7 | |||
| 203cc7ee45 | |||
| 075ba14f9f | |||
| 126caed899 | |||
| 3a2be26feb | |||
| aeea005c95 | |||
| 2a0c17480e | |||
| 584890ab25 | |||
| 759531eff5 | |||
| f582757dae | |||
| e69437ca6a | |||
| 50075e04c3 | |||
| 7f3dba49a7 | |||
| 9c098ae1fb | |||
| 078fa00bc5 | |||
| 9dc1c429f7 | |||
| 43eaed7a76 | |||
| 32d9edee1a | |||
| c49aacf389 | |||
| 2726b0556a | |||
| 2e33174d2e |
@@ -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>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2023, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014-2023, The Monero Project
|
||||
// Portions Copyright (c) 2023, Salvium (author: SRCG)
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
@@ -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() ));
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -399,8 +400,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 +421,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,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
#define HF_VERSION_ENABLE_ORACLE 2
|
||||
#define HF_VERSION_SLIPPAGE_YIELD 2
|
||||
|
||||
#define TESTNET_VERSION 5
|
||||
#define TESTNET_VERSION 6
|
||||
#define STAGENET_VERSION 1
|
||||
|
||||
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -1422,10 +1423,7 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh
|
||||
return false;
|
||||
}
|
||||
MDEBUG("Protocol tx hash: " << get_transaction_hash(b.protocol_tx));
|
||||
//CHECK_AND_ASSERT_MES(b.protocol_tx.unlock_time == height, false, "coinbase protocol transaction transaction has the wrong unlock time=" << b.protocol_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
// SRCG - we still need to make output checks
|
||||
/*
|
||||
//check outs overflow
|
||||
if(!check_outs_overflow(b.protocol_tx))
|
||||
{
|
||||
@@ -1433,8 +1431,8 @@ bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t heigh
|
||||
return false;
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(check_output_types(b.miner_tx, hf_version), false, "miner transaction has invalid output type(s) in block " << get_block_hash(b));
|
||||
*/
|
||||
CHECK_AND_ASSERT_MES(check_output_types(b.protocol_tx, hf_version), false, "protocol transaction has invalid output type(s) in block " << get_block_hash(b));
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
@@ -1491,29 +1489,25 @@ 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) {
|
||||
if (o.target.type() == typeid(txout_to_key)) {
|
||||
txout_to_key out = boost::get<txout_to_key>(o.target);
|
||||
CHECK_AND_ASSERT_MES(out.unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
|
||||
outputs[out.key] = {out.asset_type, o.amount, out.unlock_time};
|
||||
} else if (o.target.type() == typeid(txout_to_tagged_key)) {
|
||||
txout_to_tagged_key out = boost::get<txout_to_tagged_key>(o.target);
|
||||
CHECK_AND_ASSERT_MES(out.unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
|
||||
outputs[out.key] = {out.asset_type, o.amount, out.unlock_time};
|
||||
} else {
|
||||
MERROR("Block at height: " << height << " attempting to add protocol transaction with invalid type " << o.target.type().name());
|
||||
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 minted for converted 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
|
||||
// Can we have matured STAKE transactions yet?
|
||||
uint64_t stake_lock_period = get_config(m_nettype).STAKE_LOCK_PERIOD;
|
||||
if (height > stake_lock_period) {
|
||||
|
||||
// Get the data for the block that matured this time
|
||||
cryptonote::yield_block_info ybi_matured;
|
||||
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;
|
||||
// Yes - Get the staking data for the block that matured this time
|
||||
cryptonote::yield_block_info ybi_matured;
|
||||
uint64_t matured_height = height - stake_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: "
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace cryptonote
|
||||
static const command_line::arg_descriptor<std::string> arg_check_updates = {
|
||||
"check-updates"
|
||||
, "Check for new versions of monero: [disabled|notify|download|update]"
|
||||
, "notify"
|
||||
, "disabled"
|
||||
};
|
||||
static const command_line::arg_descriptor<bool> arg_fluffy_blocks = {
|
||||
"fluffy-blocks"
|
||||
@@ -519,6 +519,12 @@ namespace cryptonote
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_nettype == STAGENET) {
|
||||
folder /= std::to_string(STAGENET_VERSION);
|
||||
} else if (m_nettype == TESTNET) {
|
||||
folder /= std::to_string(TESTNET_VERSION);
|
||||
}
|
||||
|
||||
folder /= db->get_db_name();
|
||||
MGINFO("Loading blockchain from folder " << folder.string() << " ...");
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023, Salvium (author: SRCG)
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -615,8 +615,8 @@ bool t_rpc_command_executor::mining_status() {
|
||||
uint64_t daily = 86400ull / mres.block_target * mres.block_reward * ratio;
|
||||
uint64_t monthly = 86400ull / mres.block_target * 30.5 * mres.block_reward * ratio;
|
||||
uint64_t yearly = 86400ull / mres.block_target * 356 * mres.block_reward * ratio;
|
||||
tools::msg_writer() << "Expected: " << cryptonote::print_money(daily) << " monero daily, "
|
||||
<< cryptonote::print_money(monthly) << " monero monthly, " << cryptonote::print_money(yearly) << " yearly";
|
||||
tools::msg_writer() << "Expected: " << (daily / COIN) << " SALs daily, "
|
||||
<< (monthly / COIN) << " SALs monthly, " << (yearly / COIN) << " yearly";
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2016, Monero Research Labs
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// Author: Shen Noether <shen.noether@gmx.com>
|
||||
//
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2016, Monero Research Labs
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// Author: Shen Noether <shen.noether@gmx.com>
|
||||
//
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2016, Monero Research Labs
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// Author: Shen Noether <shen.noether@gmx.com>
|
||||
//
|
||||
|
||||
@@ -1486,7 +1486,7 @@ namespace cryptonote
|
||||
res.is_background_mining_enabled = lMiner.get_is_background_mining_enabled();
|
||||
store_difficulty(m_core.get_blockchain_storage().get_difficulty_for_next_block(), res.difficulty, res.wide_difficulty, res.difficulty_top64);
|
||||
|
||||
res.block_target = m_core.get_blockchain_storage().get_current_hard_fork_version() < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
|
||||
res.block_target = DIFFICULTY_TARGET_V2;
|
||||
if ( lMiner.is_mining() ) {
|
||||
res.speed = lMiner.get_speed();
|
||||
res.threads_count = lMiner.get_threads_count();
|
||||
@@ -1495,17 +1495,9 @@ namespace cryptonote
|
||||
const account_public_address& lMiningAdr = lMiner.get_mining_address();
|
||||
if (lMiner.is_mining() || lMiner.get_is_background_mining_enabled())
|
||||
res.address = get_account_address_as_str(nettype(), false, lMiningAdr);
|
||||
const uint8_t major_version = m_core.get_blockchain_storage().get_current_hard_fork_version();
|
||||
const unsigned variant = major_version >= 7 ? major_version - 6 : 0;
|
||||
switch (variant)
|
||||
{
|
||||
case 0: res.pow_algorithm = "Cryptonight"; break;
|
||||
case 1: res.pow_algorithm = "CNv1 (Cryptonight variant 1)"; break;
|
||||
case 2: case 3: res.pow_algorithm = "CNv2 (Cryptonight variant 2)"; break;
|
||||
case 4: case 5: res.pow_algorithm = "CNv4 (Cryptonight variant 4)"; break;
|
||||
case 6: case 7: case 8: case 9: res.pow_algorithm = "RandomX"; break;
|
||||
default: res.pow_algorithm = "RandomX"; break; // assumed
|
||||
}
|
||||
|
||||
res.pow_algorithm = "RandomX";
|
||||
|
||||
if (res.is_background_mining_enabled)
|
||||
{
|
||||
res.bg_idle_threshold = lMiner.get_idle_threshold();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -3178,6 +3179,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 +3553,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 +3970,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 +4038,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;
|
||||
@@ -7972,6 +7996,12 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::return_payment(const std::vector<std::string> &args_)
|
||||
{
|
||||
// Disable until appropriate hard fork
|
||||
if (m_wallet->get_current_hard_fork() < HF_VERSION_ENABLE_RETURN) {
|
||||
fail_msg_writer() << tr("return_payments are disabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!try_connect_to_daemon())
|
||||
return true;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -154,6 +155,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
@@ -1,5 +1,5 @@
|
||||
#define DEF_SALVIUM_VERSION_TAG "7f6b8da"
|
||||
#define DEF_SALVIUM_VERSION "0.2.0"
|
||||
#define DEF_SALVIUM_VERSION "0.2.6"
|
||||
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_MONERO_VERSION "0.18.3.3"
|
||||
#define DEF_MONERO_RELEASE_NAME "Zero"
|
||||
|
||||
@@ -64,8 +64,8 @@ void SubaddressAccountImpl::refresh()
|
||||
i,
|
||||
m_wallet->m_wallet->get_subaddress_as_str({i,0}),
|
||||
m_wallet->m_wallet->get_subaddress_label({i,0}),
|
||||
cryptonote::print_money(m_wallet->m_wallet->balance(i, false)),
|
||||
cryptonote::print_money(m_wallet->m_wallet->unlocked_balance(i, false))
|
||||
cryptonote::print_money(m_wallet->m_wallet->balance(i, "SAL", false)),
|
||||
cryptonote::print_money(m_wallet->m_wallet->unlocked_balance(i, "SAL", false))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
+10
-82
@@ -211,38 +211,6 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
|
||||
// TODO;
|
||||
}
|
||||
|
||||
// Light wallet callbacks
|
||||
virtual void on_lw_new_block(uint64_t height)
|
||||
{
|
||||
if (m_listener) {
|
||||
m_listener->newBlock(height);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_lw_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
|
||||
{
|
||||
if (m_listener) {
|
||||
std::string tx_hash = epee::string_tools::pod_to_hex(txid);
|
||||
m_listener->moneyReceived(tx_hash, amount);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_lw_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, uint64_t amount)
|
||||
{
|
||||
if (m_listener) {
|
||||
std::string tx_hash = epee::string_tools::pod_to_hex(txid);
|
||||
m_listener->unconfirmedMoneyReceived(tx_hash, amount);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_lw_money_spent(uint64_t height, const crypto::hash &txid, uint64_t amount)
|
||||
{
|
||||
if (m_listener) {
|
||||
std::string tx_hash = epee::string_tools::pod_to_hex(txid);
|
||||
m_listener->moneySpent(tx_hash, amount);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_device_button_request(uint64_t code)
|
||||
{
|
||||
if (m_listener) {
|
||||
@@ -952,42 +920,11 @@ string WalletImpl::keysFilename() const
|
||||
bool WalletImpl::init(const std::string &daemon_address, uint64_t upper_transaction_size_limit, const std::string &daemon_username, const std::string &daemon_password, bool use_ssl, bool lightWallet, const std::string &proxy_address)
|
||||
{
|
||||
clearStatus();
|
||||
m_wallet->set_light_wallet(lightWallet);
|
||||
if(daemon_username != "")
|
||||
m_daemon_login.emplace(daemon_username, daemon_password);
|
||||
return doInit(daemon_address, proxy_address, upper_transaction_size_limit, use_ssl);
|
||||
}
|
||||
|
||||
bool WalletImpl::lightWalletLogin(bool &isNewWallet) const
|
||||
{
|
||||
return m_wallet->light_wallet_login(isNewWallet);
|
||||
}
|
||||
|
||||
bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status)
|
||||
{
|
||||
try
|
||||
{
|
||||
tools::COMMAND_RPC_IMPORT_WALLET_REQUEST::response response;
|
||||
if(!m_wallet->light_wallet_import_wallet_request(response)){
|
||||
setStatusError(tr("Failed to send import wallet request"));
|
||||
return false;
|
||||
}
|
||||
fee = response.import_fee;
|
||||
payment_id = response.payment_id;
|
||||
new_request = response.new_request;
|
||||
request_fulfilled = response.request_fulfilled;
|
||||
payment_address = response.payment_address;
|
||||
status = response.status;
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
LOG_ERROR("Error sending import wallet request: " << e.what());
|
||||
setStatusError(e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height)
|
||||
{
|
||||
m_wallet->set_refresh_from_block_height(refresh_from_block_height);
|
||||
@@ -1010,19 +947,16 @@ void WalletImpl::setSubaddressLookahead(uint32_t major, uint32_t minor)
|
||||
|
||||
uint64_t WalletImpl::balance(uint32_t accountIndex) const
|
||||
{
|
||||
return m_wallet->balance(accountIndex, false);
|
||||
return m_wallet->balance(accountIndex, "SAL", false);
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const
|
||||
{
|
||||
return m_wallet->unlocked_balance(accountIndex, false);
|
||||
return m_wallet->unlocked_balance(accountIndex, "SAL", false);
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::blockChainHeight() const
|
||||
{
|
||||
if(m_wallet->light_wallet()) {
|
||||
return m_wallet->get_light_wallet_scanned_block_height();
|
||||
}
|
||||
return m_wallet->get_blockchain_current_height();
|
||||
}
|
||||
uint64_t WalletImpl::approximateBlockChainHeight() const
|
||||
@@ -1037,9 +971,6 @@ uint64_t WalletImpl::estimateBlockChainHeight() const
|
||||
|
||||
uint64_t WalletImpl::daemonBlockChainHeight() const
|
||||
{
|
||||
if(m_wallet->light_wallet()) {
|
||||
return m_wallet->get_light_wallet_scanned_block_height();
|
||||
}
|
||||
if (!m_is_connected)
|
||||
return 0;
|
||||
std::string err;
|
||||
@@ -1056,9 +987,6 @@ uint64_t WalletImpl::daemonBlockChainHeight() const
|
||||
|
||||
uint64_t WalletImpl::daemonBlockChainTargetHeight() const
|
||||
{
|
||||
if(m_wallet->light_wallet()) {
|
||||
return m_wallet->get_light_wallet_blockchain_height();
|
||||
}
|
||||
if (!m_is_connected)
|
||||
return 0;
|
||||
std::string err;
|
||||
@@ -1590,13 +1518,13 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
|
||||
fake_outs_count = m_wallet->adjust_mixin(mixin_count);
|
||||
|
||||
if (amount) {
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, "SAL", "SAL", cryptonote::transaction_type::TRANSFER, fake_outs_count, 0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
} else {
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_all(0, cryptonote::transaction_type::TRANSFER, "SAL", info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
} else {
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
}
|
||||
pendingTxPostProcess(transaction);
|
||||
|
||||
@@ -2183,13 +2111,13 @@ Wallet::ConnectionStatus WalletImpl::connected() const
|
||||
m_is_connected = m_wallet->check_connection(&version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS, &wallet_is_outdated, &daemon_is_outdated);
|
||||
if (!m_is_connected)
|
||||
{
|
||||
if (!m_wallet->light_wallet() && (wallet_is_outdated || daemon_is_outdated))
|
||||
if (wallet_is_outdated || daemon_is_outdated)
|
||||
return Wallet::ConnectionStatus_WrongVersion;
|
||||
else
|
||||
return Wallet::ConnectionStatus_Disconnected;
|
||||
}
|
||||
// Version check is not implemented in light wallets nodes/wallets
|
||||
if (!m_wallet->light_wallet() && (version >> 16) != CORE_RPC_VERSION_MAJOR)
|
||||
if ((version >> 16) != CORE_RPC_VERSION_MAJOR)
|
||||
return Wallet::ConnectionStatus_WrongVersion;
|
||||
return Wallet::ConnectionStatus_Connected;
|
||||
}
|
||||
@@ -2283,7 +2211,7 @@ void WalletImpl::doRefresh()
|
||||
LOG_PRINT_L3(__FUNCTION__ << ": doRefresh, rescan = "<<rescan);
|
||||
// Syncing daemon and refreshing wallet simultaneously is very resource intensive.
|
||||
// Disable refresh if wallet is disconnected or daemon isn't synced.
|
||||
if (m_wallet->light_wallet() || daemonSynced()) {
|
||||
if (daemonSynced()) {
|
||||
if(rescan)
|
||||
m_wallet->rescan_blockchain(false);
|
||||
m_wallet->refresh(trustedDaemon());
|
||||
|
||||
@@ -207,8 +207,6 @@ public:
|
||||
virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) override;
|
||||
virtual std::string make_uri(const std::string &address, const std::string &payment_id, uint64_t amount, const std::string &tx_description, const std::string &recipient_name, std::string &error) const override;
|
||||
virtual std::string getDefaultDataDir() const override;
|
||||
virtual bool lightWalletLogin(bool &isNewWallet) const override;
|
||||
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override;
|
||||
virtual bool blackballOutputs(const std::vector<std::string> &outputs, bool add) override;
|
||||
virtual bool blackballOutput(const std::string &amount, const std::string &offset) override;
|
||||
virtual bool unblackballOutput(const std::string &amount, const std::string &offset) override;
|
||||
|
||||
@@ -1066,12 +1066,6 @@ struct Wallet
|
||||
//! secondary key reuse mitigation
|
||||
virtual void keyReuseMitigation2(bool mitigation) = 0;
|
||||
|
||||
//! Light wallet authenticate and login
|
||||
virtual bool lightWalletLogin(bool &isNewWallet) const = 0;
|
||||
|
||||
//! Initiates a light wallet import wallet request
|
||||
virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) = 0;
|
||||
|
||||
//! locks/unlocks the keys file; returns true on success
|
||||
virtual bool lockKeysFile() = 0;
|
||||
virtual bool unlockKeysFile() = 0;
|
||||
|
||||
+29
-10
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -1240,6 +1241,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 +2180,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 +2201,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 +2223,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 +2653,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 +3003,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 +4867,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 +5016,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 +5254,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 +6442,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 +6465,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;
|
||||
@@ -9190,7 +9209,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
{
|
||||
MINFO("Using it");
|
||||
//req.outputs.push_back({amount, out, true}); // Rings are stored referencing global output IDs
|
||||
add_output_to_lists({amount, out});
|
||||
add_output_to_lists({amount, out, true});
|
||||
++num_found;
|
||||
seen_indices.emplace(out);
|
||||
if (out == td.m_global_output_index)
|
||||
@@ -9478,7 +9497,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
break;
|
||||
}
|
||||
}
|
||||
THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error, "Falied to find existing ring output in daemon out data");
|
||||
THROW_WALLET_EXCEPTION_IF(!found, error::wallet_internal_error, "Failed to find existing ring output in daemon out data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-38
@@ -1,4 +1,5 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
// Portions Copyright (c) 2023-2024, Salvium (author: SRCG)
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -1045,14 +1046,6 @@ private:
|
||||
bool is_deterministic() const;
|
||||
bool get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
|
||||
|
||||
/*!
|
||||
* \brief Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned.
|
||||
*/
|
||||
bool light_wallet() const { return m_light_wallet; }
|
||||
void set_light_wallet(bool light_wallet) { m_light_wallet = light_wallet; }
|
||||
uint64_t get_light_wallet_scanned_block_height() const { return m_light_wallet_scanned_block_height; }
|
||||
uint64_t get_light_wallet_blockchain_height() const { return m_light_wallet_blockchain_height; }
|
||||
|
||||
/*!
|
||||
* \brief Gets the seed language
|
||||
*/
|
||||
@@ -1186,7 +1179,7 @@ private:
|
||||
void get_unconfirmed_payments_out(std::list<std::pair<crypto::hash,wallet2::unconfirmed_transfer_details>>& unconfirmed_payments, const boost::optional<uint32_t>& subaddr_account = boost::none, const std::set<uint32_t>& subaddr_indices = {}) const;
|
||||
void get_unconfirmed_payments(std::list<std::pair<crypto::hash,wallet2::pool_payment_details>>& unconfirmed_payments, const boost::optional<uint32_t>& subaddr_account = boost::none, const std::set<uint32_t>& subaddr_indices = {}) const;
|
||||
|
||||
uint64_t get_blockchain_current_height() const { return m_light_wallet_blockchain_height ? m_light_wallet_blockchain_height : m_blockchain.size(); }
|
||||
uint64_t get_blockchain_current_height() const { return m_blockchain.size(); }
|
||||
void rescan_spent();
|
||||
void rescan_blockchain(bool hard, bool refresh = true, bool keep_key_images = false);
|
||||
bool is_transfer_unlocked(const transfer_details& td);
|
||||
@@ -1450,6 +1443,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; }
|
||||
|
||||
@@ -1646,24 +1641,6 @@ private:
|
||||
}
|
||||
template<typename T> void handle_payment_changes(const T &res, std::false_type) {}
|
||||
|
||||
// Light wallet specific functions
|
||||
// fetch unspent outs from lw node and store in m_transfers
|
||||
void light_wallet_get_unspent_outs();
|
||||
// fetch txs and store in m_payments
|
||||
void light_wallet_get_address_txs();
|
||||
// get_address_info
|
||||
bool light_wallet_get_address_info(tools::COMMAND_RPC_GET_ADDRESS_INFO::response &response);
|
||||
// Login. new_address is true if address hasn't been used on lw node before.
|
||||
bool light_wallet_login(bool &new_address);
|
||||
// Send an import request to lw node. returns info about import fee, address and payment_id
|
||||
bool light_wallet_import_wallet_request(tools::COMMAND_RPC_IMPORT_WALLET_REQUEST::response &response);
|
||||
// get random outputs from light wallet server
|
||||
void light_wallet_get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::vector<size_t> &selected_transfers, size_t fake_outputs_count);
|
||||
// Parse rct string
|
||||
bool light_wallet_parse_rct_str(const std::string& rct_string, const crypto::public_key& tx_pub_key, uint64_t internal_output_index, rct::key& decrypted_mask, rct::key& rct_commit, bool decrypt) const;
|
||||
// check if key image is ours
|
||||
bool light_wallet_key_image_is_ours(const crypto::key_image& key_image, const crypto::public_key& tx_public_key, uint64_t out_index);
|
||||
|
||||
/*
|
||||
* "attributes" are a mechanism to store an arbitrary number of string values
|
||||
* on the level of the wallet as a whole, identified by keys. Their introduction,
|
||||
@@ -1991,22 +1968,12 @@ 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
|
||||
serializable_unordered_map<crypto::hash, std::string> m_tx_device;
|
||||
|
||||
// Light wallet
|
||||
bool m_light_wallet; /* sends view key to daemon for scanning */
|
||||
uint64_t m_light_wallet_scanned_block_height;
|
||||
uint64_t m_light_wallet_blockchain_height;
|
||||
uint64_t m_light_wallet_per_kb_fee = FEE_PER_KB;
|
||||
bool m_light_wallet_connected;
|
||||
uint64_t m_light_wallet_balance;
|
||||
uint64_t m_light_wallet_unlocked_balance;
|
||||
// Light wallet info needed to populate m_payment requires 2 separate api calls (get_address_txs and get_unspent_outs)
|
||||
// We save the info from the first call in m_light_wallet_address_txs for easier lookup.
|
||||
std::unordered_map<crypto::hash, address_tx> m_light_wallet_address_txs;
|
||||
// store calculated key image for faster lookup
|
||||
serializable_unordered_map<crypto::public_key, serializable_map<uint64_t, crypto::key_image> > m_key_image_cache;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user