Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3eb986fc51 | |||
| b713a08a81 | |||
| 5bd079af4a | |||
| cd2c7c939c | |||
| 2f707e30c6 | |||
| f9726354b8 | |||
| fcd78eea7e | |||
| db740fa037 | |||
| 5971f39e7a | |||
| 02f2eb5ee9 | |||
| 02ef77bbcc |
@@ -1,4 +1,4 @@
|
||||
# Salvium Zero v0.9.3
|
||||
# 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.3
|
||||
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.3
|
||||
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.3'. 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.3
|
||||
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}
|
||||
|
||||
@@ -220,8 +220,7 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
|
||||
uint32_t txhr[24] = {0};
|
||||
unsigned int i;
|
||||
|
||||
const std::map<uint8_t, std::pair<std::string, std::string>> audit_hard_forks = get_config(net_type).AUDIT_HARD_FORKS;
|
||||
const uint64_t audit_lock_period = get_config(net_type).AUDIT_LOCK_PERIOD;
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(net_type).AUDIT_HARD_FORKS;
|
||||
|
||||
for (uint64_t h = block_start; h < block_stop; ++h)
|
||||
{
|
||||
@@ -300,7 +299,7 @@ skip:
|
||||
}
|
||||
protocol_tx_assets.insert(asset_type);
|
||||
if (protocol_tx_vout.amount > 25000000000000) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "large protocol TX amount detected from height " << (h-audit_lock_period) << delimiter << "amount:" << protocol_tx_vout.amount << std::endl;
|
||||
//std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "large protocol TX amount detected from height " << (h-audit_lock_period) << delimiter << "amount:" << protocol_tx_vout.amount << std::endl;
|
||||
}
|
||||
crypto::public_key key;
|
||||
cryptonote::get_output_public_key(protocol_tx_vout, key);
|
||||
|
||||
Binary file not shown.
@@ -1276,10 +1276,13 @@ namespace cryptonote
|
||||
if (hf_version < HF_VERSION_SALVIUM_ONE_PROOFS) {
|
||||
// Prior to the first audit, ONLY SAL was supported
|
||||
CHECK_AND_ASSERT_MES(asset_type == "SAL", false, "wrong output asset type:" << asset_type);
|
||||
} else if (hf_version == HF_VERSION_SALVIUM_ONE_PROOFS) {
|
||||
} else {
|
||||
if (tx.type == cryptonote::transaction_type::AUDIT) {
|
||||
// HERE BE DRAGONS!!!
|
||||
// SRCG: This will NOT always be the case - when we add an audit for SALx it'll need to support that as well
|
||||
// The CHANGE for an AUDIT TX must be SAL (and 0 value, and unspendable, and to the origin wallet, and ...)
|
||||
CHECK_AND_ASSERT_MES(asset_type == "SAL", false, "wrong output asset type:" << asset_type);
|
||||
// LAND AHOY!!!
|
||||
} else if (tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||
// PROTOCOL TXs are responsible for paying out SAL and SAL1 during the AUDIT
|
||||
CHECK_AND_ASSERT_MES(asset_type == "SAL1" || asset_type == "SAL", false, "wrong output asset type:" << asset_type);
|
||||
@@ -1287,9 +1290,6 @@ namespace cryptonote
|
||||
// All other TX types must only spend + create SAL1 (MINER, TRANSFER)
|
||||
CHECK_AND_ASSERT_MES(asset_type == "SAL1", false, "wrong output asset type:" << asset_type);
|
||||
}
|
||||
} else {
|
||||
// After the first AUDIT, only SAL1 is supported
|
||||
CHECK_AND_ASSERT_MES(asset_type == "SAL1", false, "wrong output asset type:" << asset_type);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
+16
-11
@@ -232,6 +232,8 @@
|
||||
#define HF_VERSION_SALVIUM_ONE_PROOFS 6
|
||||
|
||||
#define HF_VERSION_AUDIT1_PAUSE 7
|
||||
#define HF_VERSION_AUDIT2 8
|
||||
#define HF_VERSION_AUDIT2_PAUSE 9
|
||||
|
||||
#define HF_VERSION_REQUIRE_VIEW_TAGS 255
|
||||
#define HF_VERSION_ENABLE_CONVERT 255
|
||||
@@ -289,10 +291,12 @@ namespace config
|
||||
|
||||
uint32_t const GENESIS_NONCE = 10000;
|
||||
|
||||
const std::map<uint8_t, std::pair<std::string, std::string>> AUDIT_HARD_FORKS = { {HF_VERSION_AUDIT1, {"SAL", "SAL1"}} };
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> AUDIT_HARD_FORKS = {
|
||||
{HF_VERSION_AUDIT1, {30*24*10, {"SAL", "SAL1"}}},
|
||||
{HF_VERSION_AUDIT2, {30*24*14, {"SAL", "SAL1"}}}
|
||||
};
|
||||
|
||||
const uint64_t STAKE_LOCK_PERIOD = 30*24*30;
|
||||
const uint64_t AUDIT_LOCK_PERIOD = 30*24*10;
|
||||
|
||||
std::string const TREASURY_ADDRESS = "SaLvdZR6w1A21sf2Wh6jYEh1wzY4GSbT7RX6FjyPsnLsffWLrzFQeXUXJcmBLRWDzZC2YXeYe5t7qKsnrg9FpmxmEcxPHsEYfqA";
|
||||
|
||||
@@ -365,8 +369,12 @@ namespace config
|
||||
std::string const GENESIS_TX = "020001ff000180c0d0c7bbbff60302838f76f69b70bb0d0f1961a12f6082a033d22285c07d4f12ec93c28197ae2a600353414c3c2101009e8b0abce686c417a1b1344eb7337176bdca90cc928b0facec8a9516190645010000";
|
||||
uint32_t const GENESIS_NONCE = 10001;
|
||||
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> AUDIT_HARD_FORKS = {
|
||||
{HF_VERSION_AUDIT1, {30, {"SAL", "SAL1"}}},
|
||||
{HF_VERSION_AUDIT2, {40, {"SAL", "SAL1"}}},
|
||||
};
|
||||
|
||||
const uint64_t STAKE_LOCK_PERIOD = 20;
|
||||
const uint64_t AUDIT_LOCK_PERIOD = 30;
|
||||
|
||||
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.io:8443", "oracle.salvium.io:8443", "oracle.salvium.io:8443"}};
|
||||
|
||||
@@ -392,8 +400,9 @@ namespace config
|
||||
std::string const GENESIS_TX = "013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b";
|
||||
uint32_t const GENESIS_NONCE = 10002;
|
||||
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> AUDIT_HARD_FORKS = { {HF_VERSION_AUDIT1, {30, {"SAL", "SAL1"}}} };
|
||||
|
||||
const uint64_t STAKE_LOCK_PERIOD = 20;
|
||||
const uint64_t AUDIT_LOCK_PERIOD = 30;
|
||||
|
||||
std::array<std::string, 3> const ORACLE_URLS = {{"oracle.salvium.io:8443", "oracle.salvium.io:8443", "oracle.salvium.io:8443"}};
|
||||
|
||||
@@ -430,8 +439,7 @@ namespace cryptonote
|
||||
std::array<std::string, 3> const ORACLE_URLS;
|
||||
std::string const ORACLE_PUBLIC_KEY;
|
||||
uint64_t const STAKE_LOCK_PERIOD;
|
||||
uint64_t const AUDIT_LOCK_PERIOD;
|
||||
std::map<uint8_t, std::pair<std::string, std::string>> const AUDIT_HARD_FORKS;
|
||||
std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> const AUDIT_HARD_FORKS;
|
||||
std::string TREASURY_ADDRESS;
|
||||
};
|
||||
inline const config_t& get_config(network_type nettype)
|
||||
@@ -449,7 +457,6 @@ namespace cryptonote
|
||||
::config::ORACLE_URLS,
|
||||
::config::ORACLE_PUBLIC_KEY,
|
||||
::config::STAKE_LOCK_PERIOD,
|
||||
::config::AUDIT_LOCK_PERIOD,
|
||||
::config::AUDIT_HARD_FORKS,
|
||||
::config::TREASURY_ADDRESS
|
||||
};
|
||||
@@ -466,8 +473,7 @@ namespace cryptonote
|
||||
::config::testnet::ORACLE_URLS,
|
||||
::config::testnet::ORACLE_PUBLIC_KEY,
|
||||
::config::testnet::STAKE_LOCK_PERIOD,
|
||||
::config::testnet::AUDIT_LOCK_PERIOD,
|
||||
::config::AUDIT_HARD_FORKS,
|
||||
::config::testnet::AUDIT_HARD_FORKS,
|
||||
::config::testnet::TREASURY_ADDRESS
|
||||
};
|
||||
static const config_t stagenet = {
|
||||
@@ -483,8 +489,7 @@ namespace cryptonote
|
||||
::config::stagenet::ORACLE_URLS,
|
||||
::config::stagenet::ORACLE_PUBLIC_KEY,
|
||||
::config::stagenet::STAKE_LOCK_PERIOD,
|
||||
::config::stagenet::AUDIT_LOCK_PERIOD,
|
||||
::config::AUDIT_HARD_FORKS,
|
||||
::config::stagenet::AUDIT_HARD_FORKS,
|
||||
::config::stagenet::TREASURY_ADDRESS
|
||||
};
|
||||
switch (nettype)
|
||||
|
||||
@@ -1506,6 +1506,8 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
||||
case HF_VERSION_SHUTDOWN_USER_TXS:
|
||||
case HF_VERSION_SALVIUM_ONE_PROOFS:
|
||||
case HF_VERSION_AUDIT1_PAUSE:
|
||||
case HF_VERSION_AUDIT2:
|
||||
case HF_VERSION_AUDIT2_PAUSE:
|
||||
if (b.miner_tx.amount_burnt > 0) {
|
||||
CHECK_AND_ASSERT_MES(money_in_use + b.miner_tx.amount_burnt > money_in_use, false, "miner transaction is overflowed by amount_burnt");
|
||||
money_in_use += b.miner_tx.amount_burnt;
|
||||
@@ -1584,25 +1586,29 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
|
||||
// Get the audit data for the block that matures at this height
|
||||
std::vector<std::pair<yield_tx_info, uint64_t>> audit_payouts;
|
||||
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);
|
||||
const std::map<uint8_t, std::pair<std::string, std::string>> audit_hard_forks = get_config(m_nettype).AUDIT_HARD_FORKS;
|
||||
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");
|
||||
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;
|
||||
for (const auto &audit_hf : audit_hard_forks) {
|
||||
uint64_t audit_lock_period = audit_hf.second.first;
|
||||
uint64_t matured_audit_height = height - audit_lock_period - 1;
|
||||
uint8_t hf = m_hardfork->get_ideal_version(matured_audit_height);
|
||||
if (hf == audit_hf.first) {
|
||||
// Found a matching audit
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1610,76 +1616,52 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height,
|
||||
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
|
||||
@@ -1975,18 +1957,20 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the audit data for the block that matures at this height
|
||||
std::vector<std::pair<yield_tx_info, uint64_t>> audit_payouts;
|
||||
uint64_t audit_lock_period = get_config(m_nettype).AUDIT_LOCK_PERIOD;
|
||||
uint64_t matured_audit_height = height - audit_lock_period - 1;
|
||||
if (height > audit_lock_period) {
|
||||
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;
|
||||
for (const auto &audit_hf : audit_hard_forks) {
|
||||
uint64_t audit_lock_period = audit_hf.second.first;
|
||||
uint64_t matured_audit_height = height - audit_lock_period - 1;
|
||||
uint8_t hf = m_hardfork->get_ideal_version(matured_audit_height);
|
||||
const std::map<uint8_t, std::pair<std::string, std::string>> audit_hard_forks = get_config(m_nettype).AUDIT_HARD_FORKS;
|
||||
if (audit_hard_forks.find(hf) != audit_hard_forks.end()) {
|
||||
if (hf == audit_hf.first) {
|
||||
// Found a matching audit
|
||||
// Maturing height was during an audit - process accordingly
|
||||
cryptonote::audit_block_info abi_matured;
|
||||
ok = get_abi_entry(matured_audit_height, abi_matured);
|
||||
@@ -2003,7 +1987,7 @@ bool Blockchain::create_block_template(block& b, const crypto::hash *from_block,
|
||||
}
|
||||
|
||||
// Get the asset types
|
||||
const std::pair<std::string, std::string> audit_asset_types = audit_hard_forks.at(hf);
|
||||
const std::pair<std::string, std::string> audit_asset_types = audit_hf.second.second;
|
||||
|
||||
// Create the protocol_metadata entries here
|
||||
for (const auto& audit_entry: audit_payouts) {
|
||||
@@ -2017,11 +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;
|
||||
@@ -3954,9 +3958,9 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
||||
|
||||
if (tx.type == cryptonote::transaction_type::AUDIT) {
|
||||
// Make sure we are supposed to accept AUDIT txs at this point
|
||||
const std::map<uint8_t, std::pair<std::string, std::string>> audit_hard_forks = get_config(m_nettype).AUDIT_HARD_FORKS;
|
||||
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;
|
||||
CHECK_AND_ASSERT_MES(audit_hard_forks.find(hf_version) != audit_hard_forks.end(), false, "trying to audit outside an audit fork");
|
||||
std::string expected_asset_type = audit_hard_forks.at(hf_version).first;
|
||||
std::string expected_asset_type = audit_hard_forks.at(hf_version).second.first;
|
||||
CHECK_AND_ASSERT_MES(tx.source_asset_type == expected_asset_type, false, "trying to spend " << tx.source_asset_type << " coins in an AUDIT TX");
|
||||
} else {
|
||||
if (hf_version >= HF_VERSION_SALVIUM_ONE_PROOFS) {
|
||||
@@ -6279,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)
|
||||
|
||||
@@ -449,6 +449,8 @@ namespace cryptonote
|
||||
case HF_VERSION_SHUTDOWN_USER_TXS:
|
||||
case HF_VERSION_SALVIUM_ONE_PROOFS:
|
||||
case HF_VERSION_AUDIT1_PAUSE:
|
||||
case HF_VERSION_AUDIT2:
|
||||
case HF_VERSION_AUDIT2_PAUSE:
|
||||
// SRCG: subtract 20% that will be rewarded to staking users
|
||||
CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero");
|
||||
tx.amount_burnt = amount / 5;
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace cryptonote
|
||||
uint8_t type;
|
||||
crypto::public_key P_change;
|
||||
crypto::public_key return_pubkey;
|
||||
uint64_t origin_height;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------
|
||||
|
||||
@@ -52,6 +52,12 @@ const hardfork_t mainnet_hard_forks[] = {
|
||||
|
||||
// version 7 starts from block 161900, which is on or around the 14th of February, 2025. Fork time finalised on 2025-02-04. No fork voting occurs for the v7 fork.
|
||||
{ 7, 161900, 0, 1739264400 },
|
||||
|
||||
// version 8 starts from block 172000, which is on or around the 28th of February, 2025. Fork time finalised on 2025-02-24. No fork voting occurs for the v8 fork.
|
||||
{ 8, 172000, 0, 1740390000 },
|
||||
|
||||
// version 9 starts from block 179200, which is on or around the 10th of March, 2025. Fork time finalised on 2025-02-24. No fork voting occurs for the v9 fork.
|
||||
{ 9, 179200, 0, 1740393800 },
|
||||
};
|
||||
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
|
||||
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
|
||||
@@ -75,8 +81,14 @@ const hardfork_t testnet_hard_forks[] = {
|
||||
// version 6 (audit 1) starts from block 815
|
||||
{ 6, 815, 0, 1734608000 },
|
||||
|
||||
// version 7 (audit 1 pause) starts from block 900
|
||||
// version 7 (audit 1 pause, blacklist controlling payouts) starts from block 900
|
||||
{ 7, 900, 0, 1739264400 },
|
||||
|
||||
// version 8 (audit 1 resume) starts from block 950
|
||||
{ 8, 950, 0, 1739270000 },
|
||||
|
||||
// version 9 (audit 1 complete, whitelist controlling payouts) starts from block 1000
|
||||
{ 9, 1000, 0, 1739280000 },
|
||||
};
|
||||
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
|
||||
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
|
||||
|
||||
@@ -6974,9 +6974,17 @@ bool simple_wallet::transfer_main(
|
||||
std::string err;
|
||||
if (transfer_type == Audit) {
|
||||
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(m_wallet->nettype()).AUDIT_HARD_FORKS;
|
||||
uint8_t hf_version = m_wallet->get_current_hard_fork();
|
||||
const auto audit_hf = audit_hard_forks.find(hf_version);
|
||||
if (audit_hf == audit_hard_forks.end()) {
|
||||
fail_msg_writer() << tr("failed to find audit hard fork");
|
||||
return false;
|
||||
}
|
||||
unlock_block = audit_hf->second.first;
|
||||
|
||||
// Get the subaddress unlocked balances
|
||||
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = m_wallet->unlocked_balance_per_subaddress(m_current_subaddress_account, source_asset, true);
|
||||
unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
|
||||
for (const auto subaddr_index : subaddr_indices) {
|
||||
|
||||
// Skip this wallet if there is no balance unlocked to audit
|
||||
@@ -6986,7 +6994,6 @@ bool simple_wallet::transfer_main(
|
||||
|
||||
std::set<uint32_t> subaddr_indices_single;
|
||||
subaddr_indices_single.insert(subaddr_index);
|
||||
uint64_t unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
|
||||
std::vector<tools::wallet2::pending_tx> ptx_vector_audit = m_wallet->create_transactions_all(0, cryptonote::transaction_type::AUDIT, source_asset, m_wallet->get_subaddress({m_current_subaddress_account, subaddr_index}), (subaddr_index>0), 1, fake_outs_count, unlock_block, priority, extra, m_current_subaddress_account, subaddr_indices_single);
|
||||
ptx_vector.insert(ptx_vector.end(), ptx_vector_audit.begin(), ptx_vector_audit.end());
|
||||
|
||||
@@ -8396,12 +8403,12 @@ bool simple_wallet::audit(const std::vector<std::string> &args_)
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::map<uint8_t, std::pair<std::string, std::string>> audit_hard_forks = get_config(m_wallet->nettype()).AUDIT_HARD_FORKS;
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(m_wallet->nettype()).AUDIT_HARD_FORKS;
|
||||
const uint8_t hf_version = m_wallet->get_current_hard_fork();
|
||||
if (audit_hard_forks.find(hf_version) != audit_hard_forks.end()) {
|
||||
|
||||
// Get the asset types
|
||||
const std::pair<std::string, std::string> audit_asset_types = audit_hard_forks.at(hf_version);
|
||||
const std::pair<std::string, std::string> audit_asset_types = audit_hard_forks.at(hf_version).second;
|
||||
transfer_main(Audit, audit_asset_types.first, audit_asset_types.first, local_args, false);
|
||||
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#define DEF_SALVIUM_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_SALVIUM_VERSION "0.9.3"
|
||||
#define DEF_SALVIUM_VERSION "0.9.5"
|
||||
#define DEF_MONERO_VERSION_TAG "release"
|
||||
#define DEF_MONERO_VERSION "0.18.3.3"
|
||||
#define DEF_MONERO_RELEASE_NAME "Zero"
|
||||
|
||||
@@ -65,7 +65,9 @@ void SubaddressAccountImpl::refresh()
|
||||
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, "SAL", false)),
|
||||
cryptonote::print_money(m_wallet->m_wallet->unlocked_balance(i, "SAL", false))
|
||||
cryptonote::print_money(m_wallet->m_wallet->unlocked_balance(i, "SAL", false)),
|
||||
cryptonote::print_money(m_wallet->m_wallet->balance(i, "SAL1", false)),
|
||||
cryptonote::print_money(m_wallet->m_wallet->unlocked_balance(i, "SAL1", false))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ void TransactionHistoryImpl::refresh()
|
||||
ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
|
||||
ti->m_unlock_time = pd.m_unlock_time;
|
||||
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx_type));
|
||||
ti->m_asset = pd.m_asset_type;
|
||||
m_history.push_back(ti);
|
||||
|
||||
}
|
||||
@@ -195,10 +196,11 @@ void TransactionHistoryImpl::refresh()
|
||||
ti->m_timestamp = pd.m_timestamp;
|
||||
ti->m_confirmations = (wallet_height > pd.m_block_height) ? wallet_height - pd.m_block_height : 0;
|
||||
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx.type));
|
||||
ti->m_asset = pd.m_tx.source_asset_type;
|
||||
|
||||
// single output transaction might contain multiple transfers
|
||||
for (const auto &d: pd.m_dests) {
|
||||
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
|
||||
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id), d.asset_type});
|
||||
}
|
||||
|
||||
m_history.push_back(ti);
|
||||
@@ -232,9 +234,10 @@ void TransactionHistoryImpl::refresh()
|
||||
ti->m_timestamp = pd.m_timestamp;
|
||||
ti->m_confirmations = 0;
|
||||
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx.type));
|
||||
ti->m_asset = pd.m_tx.source_asset_type;
|
||||
for (const auto &d : pd.m_dests)
|
||||
{
|
||||
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id)});
|
||||
ti->m_transfers.push_back({d.amount, d.address(m_wallet->m_wallet->nettype(), pd.m_payment_id), d.asset_type});
|
||||
}
|
||||
m_history.push_back(ti);
|
||||
}
|
||||
@@ -262,6 +265,7 @@ void TransactionHistoryImpl::refresh()
|
||||
ti->m_timestamp = pd.m_timestamp;
|
||||
ti->m_confirmations = 0;
|
||||
ti->m_type = static_cast<Monero::transaction_type>(static_cast<uint8_t>(pd.m_tx_type));
|
||||
ti->m_asset = pd.m_asset_type;
|
||||
m_history.push_back(ti);
|
||||
|
||||
LOG_PRINT_L1(__FUNCTION__ << ": Unconfirmed payment found " << pd.m_amount);
|
||||
|
||||
@@ -37,8 +37,8 @@ namespace Monero {
|
||||
|
||||
TransactionInfo::~TransactionInfo() {}
|
||||
|
||||
TransactionInfo::Transfer::Transfer(uint64_t _amount, const string &_address)
|
||||
: amount(_amount), address(_address) {}
|
||||
TransactionInfo::Transfer::Transfer(uint64_t _amount, const string &_address, const string &_asset)
|
||||
: amount(_amount), address(_address), asset(_asset) {}
|
||||
|
||||
|
||||
TransactionInfoImpl::TransactionInfoImpl()
|
||||
@@ -153,5 +153,10 @@ Monero::transaction_type TransactionInfoImpl::type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
string TransactionInfoImpl::asset() const
|
||||
{
|
||||
return m_asset;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -55,6 +55,7 @@ public:
|
||||
virtual std::set<uint32_t> subaddrIndex() const override;
|
||||
virtual uint32_t subaddrAccount() const override;
|
||||
virtual std::string label() const override;
|
||||
virtual std::string asset() const override;
|
||||
|
||||
virtual std::string hash() const override;
|
||||
virtual std::time_t timestamp() const override;
|
||||
@@ -73,6 +74,7 @@ private:
|
||||
uint64_t m_fee;
|
||||
uint64_t m_blockheight;
|
||||
std::string m_description;
|
||||
std::string m_asset;
|
||||
std::set<uint32_t> m_subaddrIndex; // always unique index for incoming transfers; can be multiple indices for outgoing transfers
|
||||
uint32_t m_subaddrAccount;
|
||||
std::string m_label;
|
||||
|
||||
@@ -946,14 +946,14 @@ void WalletImpl::setSubaddressLookahead(uint32_t major, uint32_t minor)
|
||||
m_wallet->set_subaddress_lookahead(major, minor);
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::balance(uint32_t accountIndex) const
|
||||
uint64_t WalletImpl::balance(const std::string& asset, uint32_t accountIndex) const
|
||||
{
|
||||
return m_wallet->balance(accountIndex, "SAL", false);
|
||||
return m_wallet->balance(accountIndex, asset, false);
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const
|
||||
uint64_t WalletImpl::unlockedBalance(const std::string& asset, uint32_t accountIndex) const
|
||||
{
|
||||
return m_wallet->unlocked_balance(accountIndex, "SAL", false);
|
||||
return m_wallet->unlocked_balance(accountIndex, asset, false);
|
||||
}
|
||||
|
||||
uint64_t WalletImpl::blockChainHeight() const
|
||||
@@ -1436,7 +1436,7 @@ PendingTransaction *WalletImpl::createStakeTransaction(uint64_t amount, uint32_t
|
||||
// Need to populate {dst_entr, payment_id, asset_type, is_return}
|
||||
const string dst_addr = m_wallet->get_subaddress_as_str({subaddr_account, 0});//MY LOCAL (SUB)ADDRESS
|
||||
const string payment_id = "";
|
||||
const string asset_type = "SAL";
|
||||
const string asset_type = "SAL1";
|
||||
const bool is_return = false;
|
||||
|
||||
LOG_ERROR("createStakeTransaction: called");
|
||||
@@ -1568,9 +1568,41 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const Monero::transact
|
||||
adjusted_priority,
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
} else {
|
||||
transaction->m_pending_tx = m_wallet->create_transactions_all(0, converted_tx_type, asset_type, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
|
||||
adjusted_priority,
|
||||
extra, subaddr_account, subaddr_indices);
|
||||
std::vector<tools::wallet2::pending_tx> m_pending_txs;
|
||||
for (const auto subaddr_index : subaddr_indices) {
|
||||
|
||||
// Skip this wallet if there is no balance unlocked to audit
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
pendingTxPostProcess(transaction);
|
||||
|
||||
|
||||
@@ -111,8 +111,8 @@ public:
|
||||
void setTrustedDaemon(bool arg) override;
|
||||
bool trustedDaemon() const override;
|
||||
bool setProxy(const std::string &address) override;
|
||||
uint64_t balance(uint32_t accountIndex = 0) const override;
|
||||
uint64_t unlockedBalance(uint32_t accountIndex = 0) const override;
|
||||
uint64_t balance(const std::string& asset, uint32_t accountIndex = 0) const override;
|
||||
uint64_t unlockedBalance(const std::string& asset, uint32_t accountIndex = 0) const override;
|
||||
uint64_t blockChainHeight() const override;
|
||||
uint64_t approximateBlockChainHeight() const override;
|
||||
uint64_t estimateBlockChainHeight() const override;
|
||||
|
||||
@@ -209,9 +209,10 @@ struct TransactionInfo
|
||||
};
|
||||
|
||||
struct Transfer {
|
||||
Transfer(uint64_t _amount, const std::string &address);
|
||||
Transfer(uint64_t _amount, const std::string &address, const std::string &asset);
|
||||
const uint64_t amount;
|
||||
const std::string address;
|
||||
const std::string asset;
|
||||
};
|
||||
|
||||
virtual ~TransactionInfo() = 0;
|
||||
@@ -228,6 +229,7 @@ struct TransactionInfo
|
||||
virtual std::string label() const = 0;
|
||||
virtual uint64_t confirmations() const = 0;
|
||||
virtual uint64_t unlockTime() const = 0;
|
||||
virtual std::string asset() const = 0;
|
||||
//! transaction_id
|
||||
virtual std::string hash() const = 0;
|
||||
virtual std::time_t timestamp() const = 0;
|
||||
@@ -326,25 +328,35 @@ struct Subaddress
|
||||
|
||||
struct SubaddressAccountRow {
|
||||
public:
|
||||
SubaddressAccountRow(std::size_t _rowId, const std::string &_address, const std::string &_label, const std::string &_balance, const std::string &_unlockedBalance):
|
||||
SubaddressAccountRow(std::size_t _rowId, const std::string &_address, const std::string &_label, const std::string &_balance, const std::string &_unlockedBalance, const std::string &_balance_sal1, const std::string &_unlockedBalance_sal1):
|
||||
m_rowId(_rowId),
|
||||
m_address(_address),
|
||||
m_label(_label),
|
||||
m_balance(_balance),
|
||||
m_unlockedBalance(_unlockedBalance) {}
|
||||
m_balance_sal(_balance),
|
||||
m_unlockedBalance_sal(_unlockedBalance),
|
||||
m_balance_sal1(_balance_sal1),
|
||||
m_unlockedBalance_sal1(_unlockedBalance_sal1) {}
|
||||
|
||||
private:
|
||||
std::size_t m_rowId;
|
||||
std::string m_address;
|
||||
std::string m_label;
|
||||
std::string m_balance;
|
||||
std::string m_unlockedBalance;
|
||||
std::string m_balance_sal;
|
||||
std::string m_balance_sal1;
|
||||
std::string m_unlockedBalance_sal;
|
||||
std::string m_unlockedBalance_sal1;
|
||||
public:
|
||||
std::string extra;
|
||||
std::string getAddress() const {return m_address;}
|
||||
std::string getLabel() const {return m_label;}
|
||||
std::string getBalance() const {return m_balance;}
|
||||
std::string getUnlockedBalance() const {return m_unlockedBalance;}
|
||||
std::string getBalance(const std::string& asset) const {
|
||||
if (asset == "SAL") return m_balance_sal;
|
||||
else return m_balance_sal1;
|
||||
}
|
||||
std::string getUnlockedBalance(const std::string& asset) const {
|
||||
if (asset == "SAL") return m_unlockedBalance_sal;
|
||||
else return m_unlockedBalance_sal1;
|
||||
}
|
||||
std::size_t getRowId() const {return m_rowId;}
|
||||
};
|
||||
|
||||
@@ -642,18 +654,18 @@ struct Wallet
|
||||
virtual void setTrustedDaemon(bool arg) = 0;
|
||||
virtual bool trustedDaemon() const = 0;
|
||||
virtual bool setProxy(const std::string &address) = 0;
|
||||
virtual uint64_t balance(uint32_t accountIndex = 0) const = 0;
|
||||
uint64_t balanceAll() const {
|
||||
virtual uint64_t balance(const std::string &asset, uint32_t accountIndex = 0) const = 0;
|
||||
uint64_t balanceAll(const std::string &asset) const {
|
||||
uint64_t result = 0;
|
||||
for (uint32_t i = 0; i < numSubaddressAccounts(); ++i)
|
||||
result += balance(i);
|
||||
result += balance(asset, i);
|
||||
return result;
|
||||
}
|
||||
virtual uint64_t unlockedBalance(uint32_t accountIndex = 0) const = 0;
|
||||
uint64_t unlockedBalanceAll() const {
|
||||
virtual uint64_t unlockedBalance(const std::string &asset, uint32_t accountIndex = 0) const = 0;
|
||||
uint64_t unlockedBalanceAll(const std::string &asset) const {
|
||||
uint64_t result = 0;
|
||||
for (uint32_t i = 0; i < numSubaddressAccounts(); ++i)
|
||||
result += unlockedBalance(i);
|
||||
result += unlockedBalance(asset, i);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+32
-14
@@ -2573,10 +2573,16 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
if (!miner_tx && !pool)
|
||||
process_unconfirmed(txid, tx, height);
|
||||
|
||||
std::string source_asset =
|
||||
(tx.type == cryptonote::transaction_type::MINER) ? "SAL" :
|
||||
(tx.type == cryptonote::transaction_type::PROTOCOL) ? "SAL" :
|
||||
tx.source_asset_type;
|
||||
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) {
|
||||
source_asset = "SAL1";
|
||||
}
|
||||
} else if (tx.type == cryptonote::transaction_type::MINER && tx.type == cryptonote::transaction_type::PROTOCOL) {
|
||||
source_asset = "SAL";
|
||||
} else {
|
||||
source_asset = tx.source_asset_type;
|
||||
}
|
||||
|
||||
// per receiving subaddress index
|
||||
std::unordered_map<cryptonote::subaddress_index, std::map<std::string, uint64_t>> tx_money_got_in_outs;
|
||||
@@ -2762,7 +2768,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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7060,22 +7069,27 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, const std::string& asse
|
||||
std::map<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major, const std::string& asset_type, bool strict) const
|
||||
{
|
||||
std::map<uint32_t, uint64_t> amount_per_subaddr;
|
||||
for (const auto& idx: m_transfers_indices.at(asset_type))
|
||||
{
|
||||
const transfer_details& td = m_transfers[idx];
|
||||
if (td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen)
|
||||
if (m_transfers_indices.count(asset_type) > 0) {
|
||||
for (const auto& idx: m_transfers_indices.at(asset_type))
|
||||
{
|
||||
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
||||
if (found == amount_per_subaddr.end())
|
||||
amount_per_subaddr[td.m_subaddr_index.minor] = td.amount();
|
||||
else
|
||||
found->second += td.amount();
|
||||
const transfer_details& td = m_transfers[idx];
|
||||
if (td.m_subaddr_index.major == index_major && !is_spent(td, strict) && !td.m_frozen)
|
||||
{
|
||||
auto found = amount_per_subaddr.find(td.m_subaddr_index.minor);
|
||||
if (found == amount_per_subaddr.end())
|
||||
amount_per_subaddr[td.m_subaddr_index.minor] = td.amount();
|
||||
else
|
||||
found->second += td.amount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!strict)
|
||||
{
|
||||
for (const auto& utx: m_unconfirmed_txs)
|
||||
{
|
||||
// Skip UTXs that have the wrong asset type
|
||||
if (utx.second.m_tx.source_asset_type != asset_type) continue;
|
||||
if (utx.second.m_subaddr_account == index_major && utx.second.m_state != wallet2::unconfirmed_transfer_details::failed)
|
||||
{
|
||||
// all changes go to 0-th subaddress (in the current subaddress account)
|
||||
@@ -7116,6 +7130,10 @@ std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> wallet2::
|
||||
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> amount_per_subaddr;
|
||||
const uint64_t blockchain_height = get_blockchain_current_height();
|
||||
const uint64_t now = time(NULL);
|
||||
if (m_transfers_indices.count(asset_type) == 0) {
|
||||
return amount_per_subaddr;
|
||||
}
|
||||
|
||||
for(const auto& idx: m_transfers_indices[asset_type])
|
||||
{
|
||||
transfer_details& td = m_transfers[idx];
|
||||
|
||||
@@ -1136,6 +1136,13 @@ namespace tools
|
||||
|
||||
try
|
||||
{
|
||||
// Get the audit information
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(m_wallet->nettype()).AUDIT_HARD_FORKS;
|
||||
const uint8_t hf_version = m_wallet->get_current_hard_fork();
|
||||
if (audit_hard_forks.find(hf_version) == audit_hard_forks.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<wallet2::pending_tx> ptx_vector_all;
|
||||
// Get the subaddress unlocked balances
|
||||
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> unlocked_balance_per_subaddr = m_wallet->unlocked_balance_per_subaddress(req.account_index, asset_type, true);
|
||||
@@ -1148,7 +1155,7 @@ namespace tools
|
||||
subaddr_indices_single.insert(subaddr_index);
|
||||
uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
|
||||
uint32_t priority = m_wallet->adjust_priority(0);
|
||||
uint64_t unlock_block = get_config(m_wallet->nettype()).AUDIT_LOCK_PERIOD;
|
||||
uint64_t unlock_block = audit_hard_forks.at(hf_version).first;
|
||||
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_all(0, cryptonote::transaction_type::AUDIT, asset_type, m_wallet->get_subaddress({req.account_index, subaddr_index}), (subaddr_index > 0), 1, mixin, unlock_block, priority, extra, req.account_index, subaddr_indices_single);
|
||||
ptx_vector_all.insert(ptx_vector_all.end(), ptx_vector.begin(), ptx_vector.end());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user