Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9570c7a910 | |||
| 23756691b7 | |||
| 3eb986fc51 | |||
| b713a08a81 |
@@ -1,4 +1,4 @@
|
||||
# Salvium Zero v0.9.4
|
||||
# Salvium Zero v0.9.5
|
||||
|
||||
Copyright (c) 2023-2024, Salvium
|
||||
Portions Copyright (c) 2014-2023, The Monero Project
|
||||
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
|
||||
|
||||
```bash
|
||||
cd salvium
|
||||
git checkout v0.9.4
|
||||
git checkout v0.9.5
|
||||
make
|
||||
```
|
||||
|
||||
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
|
||||
```bash
|
||||
git clone https://github.com/salvium/salvium
|
||||
cd salvium
|
||||
git checkout v0.9.4
|
||||
git checkout v0.9.5
|
||||
```
|
||||
|
||||
* Build:
|
||||
@@ -370,10 +370,10 @@ application.
|
||||
cd salvium
|
||||
```
|
||||
|
||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.9.4'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.9.5'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
|
||||
```bash
|
||||
git checkout v0.9.4
|
||||
git checkout v0.9.5
|
||||
```
|
||||
|
||||
* If you are on a 64-bit system, run:
|
||||
|
||||
@@ -142,8 +142,7 @@ set(blockchain_scanner_private_headers)
|
||||
monero_private_headers(blockchain_scanner
|
||||
${blockchain_scanner_private_headers})
|
||||
|
||||
if (BUILD_TAG)
|
||||
else()
|
||||
if (BUILD_AUDIT)
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp")
|
||||
set(blockchain_audit_sources
|
||||
blockchain_audit.cpp
|
||||
@@ -330,8 +329,7 @@ set_property(TARGET blockchain_scanner
|
||||
OUTPUT_NAME "salvium-blockchain-scanner")
|
||||
install(TARGETS blockchain_scanner DESTINATION bin)
|
||||
|
||||
if (BUILD_TAG)
|
||||
else()
|
||||
if (BUILD_AUDIT)
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp")
|
||||
monero_add_executable(blockchain_audit
|
||||
${blockchain_audit_sources}
|
||||
|
||||
Binary file not shown.
@@ -1611,103 +1611,57 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(m_nettype).AUDIT_HARD_FORKS;
|
||||
uint64_t audit_lock_period = get_config(m_nettype).AUDIT_LOCK_PERIOD;
|
||||
uint64_t matured_audit_height = height - audit_lock_period - 1;
|
||||
uint8_t hf = m_hardfork->get_ideal_version(matured_audit_height);
|
||||
if (audit_hard_forks.find(hf) != audit_hard_forks.end()) {
|
||||
// Maturing height was during an audit - process accordingly
|
||||
cryptonote::audit_block_info abi_matured;
|
||||
ok = get_abi_entry(matured_audit_height, abi_matured);
|
||||
if (!ok) {
|
||||
LOG_PRINT_L1("Block at height: " << height << " - failed to obtain audit block information - aborting");
|
||||
return false;
|
||||
} else if (abi_matured.locked_coins_this_block == 0) {
|
||||
LOG_PRINT_L1("Block at height: " << height << " - no audit payouts due - skipping");
|
||||
} else {
|
||||
// Iterate over the cached data for audits, calculating the audit payouts due
|
||||
if (!calculate_audit_payouts(matured_audit_height, audit_payouts)) {
|
||||
LOG_ERROR("Block at height: " << height << " - Failed to obtain audit payout information - aborting");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Check we have the correct number of entries
|
||||
CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == yield_payouts.size() + audit_payouts.size(), false, "Invalid number of outputs in protocol_tx - aborting");
|
||||
|
||||
// go through each vout and validate
|
||||
std::set<crypto::public_key> used_keys;
|
||||
for (auto& o : b.protocol_tx.vout) {
|
||||
// gather the output data
|
||||
uint64_t out_amount;
|
||||
uint64_t out_unlock_time;
|
||||
std::string out_asset_type;
|
||||
//std::set<crypto::public_key> used_keys;
|
||||
|
||||
// Merge the yield and audit payouts into an iterable vector
|
||||
std::vector<std::pair<yield_tx_info, uint64_t>> payouts{yield_payouts};
|
||||
payouts.insert(payouts.end(), audit_payouts.begin(), audit_payouts.end());
|
||||
/*
|
||||
if (hf_version >= HF_VERSION_AUDIT2) {
|
||||
std::sort(payouts.begin(), payouts.end(), [](const auto& lhs, const auto& rhs) {
|
||||
// If block heights are different (only possible with mixed AUDIT+STAKE) sort by them first
|
||||
if (lhs.first.block_height < rhs.first.block_height) return true;
|
||||
if (lhs.first.block_height > rhs.first.block_height) return false;
|
||||
|
||||
// If output keys are different, sort by them second
|
||||
if (lhs.first.return_address < rhs.first.return_address) return true;
|
||||
if (lhs.first.return_address > rhs.first.return_address) return false;
|
||||
|
||||
// If block heights _and_ output keys are same, sort by amount third
|
||||
return lhs.second < rhs.second;
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
size_t output_idx = 0;
|
||||
for (auto it = payouts.begin(); it != payouts.end(); it++, output_idx++) {
|
||||
|
||||
// Verify the output key
|
||||
crypto::public_key out_key;
|
||||
if (o.target.type() == typeid(txout_to_key)) {
|
||||
txout_to_key out = boost::get<txout_to_key>(o.target);
|
||||
out_unlock_time = out.unlock_time;
|
||||
out_asset_type = out.asset_type;
|
||||
out_key = out.key;
|
||||
out_amount = o.amount;
|
||||
} else if (o.target.type() == typeid(txout_to_tagged_key)) {
|
||||
txout_to_tagged_key out = boost::get<txout_to_tagged_key>(o.target);
|
||||
out_unlock_time = out.unlock_time;
|
||||
out_asset_type = out.asset_type;
|
||||
out_key = out.key;
|
||||
out_amount = o.amount;
|
||||
} else {
|
||||
MERROR("Block at height: " << height << " attempting to add protocol transaction with invalid type " << o.target.type().name());
|
||||
return false;
|
||||
}
|
||||
cryptonote::get_output_public_key(b.protocol_tx.vout[output_idx], out_key);
|
||||
CHECK_AND_ASSERT_MES(out_key == it->first.return_address, false, "Incorrect output key detected in protocol_tx");
|
||||
|
||||
// Check if key has already been seen
|
||||
if (used_keys.count(out_key) != 0) {
|
||||
LOG_ERROR("Block at height: " << height << " - Duplicated output key " << out_key << " for protocol TX - aborting");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add key to list of already-seen
|
||||
used_keys.insert(out_key);
|
||||
|
||||
// check if there is entry in the yield payouts or audit payouts for this output
|
||||
std::string expected_output_asset_type = "SAL";
|
||||
auto found_yield = std::find_if(yield_payouts.begin(), yield_payouts.end(), [&](const std::pair<yield_tx_info, uint64_t>& p) {
|
||||
return p.first.return_address == out_key;
|
||||
});
|
||||
auto found_audit = std::find_if(audit_payouts.begin(), audit_payouts.end(), [&](const std::pair<yield_tx_info, uint64_t>& p) {
|
||||
return p.first.return_address == out_key;
|
||||
});
|
||||
if (found_yield == yield_payouts.end() && found_audit == audit_payouts.end()) {
|
||||
MERROR("Block at height: " << height << " - Failed to locate output for protocol TX - rejecting block");
|
||||
return false;
|
||||
} else if (found_audit == audit_payouts.end()) {
|
||||
// Verify the output amount
|
||||
CHECK_AND_ASSERT_MES(b.protocol_tx.vout[output_idx].amount == it->second, false, "Incorrect output amount detected in protocol_tx");
|
||||
|
||||
// Found a YIELD entry
|
||||
CHECK_AND_ASSERT_MES(out_amount == found_yield->second, false, "Incorrect value for protocol TX YIELD amount");
|
||||
uint8_t hf_yield = m_hardfork->get_ideal_version(found_yield->first.block_height);
|
||||
if (hf_yield >= HF_VERSION_SALVIUM_ONE_PROOFS)
|
||||
expected_output_asset_type = "SAL1";
|
||||
// Verify the output asset type
|
||||
std::string out_asset_type;
|
||||
cryptonote::get_output_asset_type(b.protocol_tx.vout[output_idx], out_asset_type);
|
||||
uint8_t hf_yield = m_hardfork->get_ideal_version(it->first.block_height);
|
||||
if (hf_yield >= HF_VERSION_SALVIUM_ONE_PROOFS)
|
||||
CHECK_AND_ASSERT_MES(out_asset_type == "SAL1", false, "Incorrect output asset_type (!= SAL1) detected in protocol_tx");
|
||||
else
|
||||
CHECK_AND_ASSERT_MES(out_asset_type == "SAL", false, "Incorrect output asset_type (!= SAL) detected in protocol_tx");
|
||||
|
||||
} else if (found_yield == yield_payouts.end()) {
|
||||
|
||||
// Found an AUDIT entry
|
||||
CHECK_AND_ASSERT_MES(out_amount == found_audit->second, false, "Incorrect value for protocol TX AUDIT amount");
|
||||
uint8_t hf_audit = m_hardfork->get_ideal_version(found_audit->first.block_height);
|
||||
if (hf_audit >= HF_VERSION_SALVIUM_ONE_PROOFS)
|
||||
expected_output_asset_type = "SAL1";
|
||||
|
||||
} else {
|
||||
|
||||
// Duplicate entry in yield + audit?!?!?
|
||||
MERROR("Block at height: " << height << " - Duplicated YIELD and AUDIT keys found for protocol TX - rejecting block");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check other fields
|
||||
CHECK_AND_ASSERT_MES(out_unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid unlock time on protocol_tx output");
|
||||
CHECK_AND_ASSERT_MES(expected_output_asset_type == out_asset_type, false, "Incorrect asset type detected for protocol TX ouput - rejecting block");
|
||||
// Verify the output unlock time
|
||||
uint64_t out_unlock_time;
|
||||
cryptonote::get_output_unlock_time(b.protocol_tx.vout[output_idx], out_unlock_time);
|
||||
CHECK_AND_ASSERT_MES(out_unlock_time == CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "Invalid output unlock time on protocol_tx output");
|
||||
}
|
||||
|
||||
// Everything checks out
|
||||
@@ -2003,6 +1957,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
entry.type = cryptonote::transaction_type::STAKE;
|
||||
entry.P_change = yield_entry.first.P_change;
|
||||
entry.return_pubkey = yield_entry.first.return_pubkey;
|
||||
entry.origin_height = start_height;
|
||||
protocol_entries.push_back(entry);
|
||||
}
|
||||
}
|
||||
@@ -2046,12 +2001,31 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
entry.type = cryptonote::transaction_type::AUDIT;
|
||||
entry.P_change = audit_entry.first.P_change;
|
||||
entry.return_pubkey = audit_entry.first.return_pubkey;
|
||||
entry.origin_height = matured_audit_height;
|
||||
protocol_entries.push_back(entry);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// From v8, we sort the protocol_tx outputs by ORIGIN_HEIGHT, OUTPUT_KEY, AMOUNT
|
||||
if (b.major_version >= HF_VERSION_AUDIT2) {
|
||||
std::sort(protocol_entries.begin(), protocol_entries.end(), [](const auto& lhs, const auto& rhs) {
|
||||
// If origin block heights are different (only possible with mixed AUDIT+STAKE) sort by them first
|
||||
if (lhs.origin_height < rhs.origin_height) return true;
|
||||
if (lhs.origin_height > rhs.origin_height) return false;
|
||||
|
||||
// If output keys are different, sort by them second
|
||||
if (lhs.return_address < rhs.return_address) return true;
|
||||
if (lhs.return_address > rhs.return_address) return false;
|
||||
|
||||
// If block heights _and_ output keys are same, sort by amount third
|
||||
return lhs.amount_burnt < rhs.amount_burnt;
|
||||
});
|
||||
}
|
||||
*/
|
||||
|
||||
// Time to construct the protocol_tx
|
||||
uint64_t protocol_fee = 0;
|
||||
@@ -6309,7 +6283,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "5065d5361119a526b7a45e9e5bdf1d5be86f80e9eb43b0398bf0e47489c81c6d";
|
||||
static const char expected_block_hashes_hash[] = "131b18108fb3382b4fa82d4eb6cca8f9e1e0ee2aa7893e572361ca0c2c4118e6";
|
||||
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
|
||||
{
|
||||
if (get_checkpoints == nullptr || !m_fast_sync)
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace cryptonote
|
||||
uint8_t type;
|
||||
crypto::public_key P_change;
|
||||
crypto::public_key return_pubkey;
|
||||
uint64_t origin_height;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
@@ -3200,6 +3200,25 @@ bool simple_wallet::set_freeze_incoming_payments(const std::vector<std::string>
|
||||
return true;
|
||||
}
|
||||
|
||||
bool simple_wallet::set_send_change_back_to_subaddress(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->send_change_back_to_subaddress(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())
|
||||
@@ -3562,7 +3581,9 @@ simple_wallet::simple_wallet()
|
||||
"inactivity-lock-timeout <unsigned int>\n "
|
||||
" 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."));
|
||||
" Whether to have incoming payments automatically frozen, so they cannot be spent erroneously.\n"
|
||||
"send-change-back-to-subaddress <1|0>\n "
|
||||
" Whether to have change from transactions sent back subaddresses (1) or to main address (0) (ignored for AUDIT commands)."));
|
||||
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."));
|
||||
@@ -3979,6 +4000,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
|
||||
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();
|
||||
success_msg_writer() << "send-change-back-to-subaddress = " << m_wallet->is_send_change_back_to_subaddress_enabled();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -4047,6 +4069,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
|
||||
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"));
|
||||
CHECK_SIMPLE_VARIABLE("send-change-back-to-subaddress", set_send_change_back_to_subaddress, tr("0 or 1"));
|
||||
}
|
||||
fail_msg_writer() << tr("set: unrecognized argument(s)");
|
||||
return true;
|
||||
|
||||
@@ -156,6 +156,7 @@ namespace cryptonote
|
||||
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_send_change_back_to_subaddress(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 "@VERSIONTAG@"
|
||||
#define DEF_SALVIUM_VERSION "0.9.4"
|
||||
#define DEF_SALVIUM_VERSION "0.9.5a"
|
||||
#define DEF_MONERO_VERSION_TAG "release"
|
||||
#define DEF_MONERO_VERSION "0.18.3.3"
|
||||
#define DEF_MONERO_RELEASE_NAME "Zero"
|
||||
|
||||
+29
-18
@@ -1569,27 +1569,38 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const Monero::transact
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
} else {
|
||||
std::vector<tools::wallet2::pending_tx> m_pending_txs;
|
||||
for (auto it = subaddr_indices.begin(); it != subaddr_indices.end(); ++it) {
|
||||
for (const auto subaddr_index : subaddr_indices) {
|
||||
|
||||
// Skip this wallet if there is no balance unlocked to audit
|
||||
const auto unlocked_balance_per_subaddr = m_wallet->unlocked_balance_per_subaddress(subaddr_account, "SAL", true);
|
||||
if (unlocked_balance_per_subaddr.count(*it) == 0) continue;
|
||||
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = m_wallet->unlocked_balance_per_subaddress(subaddr_account, asset_type, true);
|
||||
if (unlocked_balance_per_subaddr.count(subaddr_index) == 0) continue;
|
||||
|
||||
const auto result = m_wallet->create_transactions_all(
|
||||
0,
|
||||
converted_tx_type,
|
||||
asset_type,
|
||||
m_wallet->get_subaddress({subaddr_account, *it}),
|
||||
((*it) > 0),
|
||||
1,
|
||||
fake_outs_count,
|
||||
0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra,
|
||||
subaddr_account,
|
||||
std::set<uint32_t> {*it}
|
||||
);
|
||||
m_pending_txs.insert(m_pending_txs.end(), result.begin(), result.end());
|
||||
try {
|
||||
|
||||
const auto result = m_wallet->create_transactions_all(0,
|
||||
converted_tx_type,
|
||||
asset_type,
|
||||
m_wallet->get_subaddress({subaddr_account, subaddr_index}),
|
||||
(subaddr_index > 0),
|
||||
1,
|
||||
fake_outs_count,
|
||||
0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra,
|
||||
subaddr_account,
|
||||
std::set<uint32_t> {subaddr_index}
|
||||
);
|
||||
m_pending_txs.insert(m_pending_txs.end(), result.begin(), result.end());
|
||||
|
||||
} catch (const std::exception &e) {
|
||||
|
||||
// Let's skip this wallet - we have already reported the error
|
||||
if (unlocked_balance_per_subaddr[subaddr_index].first < 250000000) {
|
||||
std::ostringstream writer;
|
||||
writer << boost::format(tr("Subaddress index %u has insufficient funds (%s) to pay for audit")) % subaddr_index % print_money(unlocked_balance_per_subaddr[subaddr_index].first);
|
||||
setStatusError(writer.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
transaction->m_pending_tx = m_pending_txs;
|
||||
}
|
||||
|
||||
+25
-7
@@ -1252,6 +1252,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
|
||||
m_credits_target(0),
|
||||
m_enable_multisig(false),
|
||||
m_freeze_incoming_payments(false),
|
||||
m_send_change_back_to_subaddress(false),
|
||||
m_pool_info_query_time(0),
|
||||
m_has_ever_refreshed_from_node(false),
|
||||
m_allow_mismatched_daemon_version(false)
|
||||
@@ -2574,12 +2575,12 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
process_unconfirmed(txid, tx, height);
|
||||
|
||||
std::string source_asset;
|
||||
if (use_fork_rules(get_salvium_one_proofs_fork(), 0)) {
|
||||
if (tx.type == cryptonote::transaction_type::MINER && tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||
if (tx.type == cryptonote::transaction_type::MINER || tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||
if (use_fork_rules(get_salvium_one_proofs_fork(), 0)) {
|
||||
source_asset = "SAL1";
|
||||
} else {
|
||||
source_asset = "SAL";
|
||||
}
|
||||
} else if (tx.type == cryptonote::transaction_type::MINER && tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||
source_asset = "SAL";
|
||||
} else {
|
||||
source_asset = tx.source_asset_type;
|
||||
}
|
||||
@@ -2768,7 +2769,10 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
crypto::public_key pk_locked_coins = crypto::null_pkey;
|
||||
THROW_WALLET_EXCEPTION_IF(!get_output_public_key(td_origin.m_tx.vout[td_origin.m_internal_output_index], pk_locked_coins), error::wallet_internal_error, "Failed to get output public key for locked coins");
|
||||
// At this point, we need to clear the "locked coins" count, because otherwise we will be counting yield stakes twice in our balance
|
||||
THROW_WALLET_EXCEPTION_IF(!m_locked_coins.erase(pk_locked_coins), error::wallet_internal_error, "Failed to remove protocol_tx entry from m_locked_coins");
|
||||
//THROW_WALLET_EXCEPTION_IF(!m_locked_coins.erase(pk_locked_coins), error::wallet_internal_error, "Failed to remove protocol_tx entry from m_locked_coins");
|
||||
if (!m_locked_coins.erase(pk_locked_coins)) {
|
||||
LOG_ERROR("Failed to remove protocol_tx entry from m_locked_coins - possible duplicate output key detected");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5141,6 +5145,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
|
||||
value2.SetInt(m_freeze_incoming_payments ? 1 : 0);
|
||||
json.AddMember("freeze_incoming_payments", value2, json.GetAllocator());
|
||||
|
||||
value2.SetInt(m_send_change_back_to_subaddress ? 1 : 0);
|
||||
json.AddMember("send_change_back_to_subaddress", value2, json.GetAllocator());
|
||||
|
||||
// Serialize the JSON object
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
@@ -5288,6 +5295,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
|
||||
m_credits_target = 0;
|
||||
m_enable_multisig = false;
|
||||
m_freeze_incoming_payments = false;
|
||||
m_send_change_back_to_subaddress = false;
|
||||
m_allow_mismatched_daemon_version = false;
|
||||
}
|
||||
else if(json.IsObject())
|
||||
@@ -5527,6 +5535,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
|
||||
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;
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, send_change_back_to_subaddress, int, Int, false, false);
|
||||
m_send_change_back_to_subaddress = field_send_change_back_to_subaddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -10241,8 +10251,16 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
|
||||
cryptonote::tx_destination_entry change_dts = AUTO_VAL_INIT(change_dts);
|
||||
change_dts.amount = found_money - needed_money;
|
||||
change_dts.asset_type = source_asset;
|
||||
change_dts.addr = get_subaddress({subaddr_account, subaddr_index});
|
||||
change_dts.is_subaddress = subaddr_account != 0 || subaddr_index != 0;
|
||||
|
||||
// Lazy devs can't be bothered to code a proper solution for get_transfer_by_txid,
|
||||
// so we have to provide a hack for them and their poor code.
|
||||
if (m_send_change_back_to_subaddress || tx_type == cryptonote::transaction_type::AUDIT) {
|
||||
change_dts.addr = get_subaddress({subaddr_account, subaddr_index});
|
||||
change_dts.is_subaddress = subaddr_account != 0 || subaddr_index != 0;
|
||||
} else {
|
||||
change_dts.addr = get_subaddress({subaddr_account, 0});
|
||||
change_dts.is_subaddress = subaddr_account != 0;
|
||||
}
|
||||
change_dts.is_change = true;
|
||||
splitted_dsts.push_back(change_dts);
|
||||
|
||||
|
||||
@@ -1450,6 +1450,8 @@ private:
|
||||
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_send_change_back_to_subaddress_enabled() const { return m_send_change_back_to_subaddress; }
|
||||
void send_change_back_to_subaddress(bool enable) { m_send_change_back_to_subaddress = 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; }
|
||||
|
||||
@@ -1982,6 +1984,7 @@ private:
|
||||
uint64_t m_credits_target;
|
||||
bool m_enable_multisig;
|
||||
bool m_freeze_incoming_payments;
|
||||
bool m_send_change_back_to_subaddress;
|
||||
bool m_allow_mismatched_daemon_version;
|
||||
|
||||
// Aux transaction data from device
|
||||
|
||||
Reference in New Issue
Block a user