mirror of
https://codeberg.org/nahuhh/wownero
synced 2026-03-04 21:57:40 -05:00
Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4a5778dd6 | ||
|
|
cce5708153 | ||
|
|
0a97b3784d | ||
|
|
a8790e240c | ||
|
|
c929c2a6bb | ||
|
|
741adad93a | ||
|
|
73b17fcb62 | ||
|
|
f3ee225f29 | ||
|
|
f165101429 | ||
|
|
d2554341b1 | ||
|
|
c1632fb30c | ||
|
|
17cd68f865 | ||
|
|
5c6eb96036 | ||
|
|
b67c96af71 | ||
|
|
88fd5fb494 | ||
|
|
5c3195dac9 | ||
|
|
8386c6df2c | ||
|
|
9d952da3a0 | ||
|
|
2320fb5549 | ||
|
|
b40a81c694 | ||
|
|
308a8f69ad | ||
|
|
b491ff61c5 | ||
|
|
bb0ac27a4a | ||
|
|
835caf3722 | ||
|
|
9021fe99b1 | ||
|
|
bbd251c48f | ||
|
|
00c6056e98 | ||
|
|
47f7cf68ae | ||
|
|
c4bdd5699c | ||
|
|
7e6b4601c3 | ||
|
|
d4f07b40de | ||
|
|
1bbfeb325c | ||
|
|
dc1e56d815 | ||
|
|
332ac6a03a | ||
|
|
ae255e3857 | ||
|
|
7cf07e9319 | ||
|
|
d904ea08a1 | ||
|
|
0da1f14aaf | ||
|
|
583eaf3ccb | ||
|
|
ee45ef2c9e | ||
|
|
7ba6d69196 | ||
|
|
83e5d6a829 | ||
|
|
a09d5ea211 | ||
|
|
2998b929d5 | ||
|
|
44e0f9eebf | ||
|
|
00bf0b5ef0 | ||
|
|
d1176c5ef5 | ||
|
|
cbf07f01ba | ||
|
|
9c828a281b | ||
|
|
a5253e2fb4 | ||
|
|
ff3a667a90 | ||
|
|
a3a84378eb | ||
|
|
202d568676 | ||
|
|
47aa3f296d | ||
|
|
6bdd11abe2 | ||
|
|
6486269929 |
@@ -95,7 +95,7 @@ Dates are provided in the format YYYY-MM-DD.
|
||||
| ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| 1 | 2018-04-01 | v7 | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
|
||||
| 6969 | 2018-04-24 | v8 | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
|
||||
| 53666 | 2018-10-06 | v9 | v0.3.0.0 | v0.3.0.0 | Cryptonight variant 2, LWMA v2, ringsize = 22, XXX
|
||||
| 53666 | 2018-10-06 | v9 | v0.3.0.0 | v0.3.1.0 | Cryptonight variant 2, LWMA v2, ringsize = 22, XXX
|
||||
|
||||
X's indicate that these details have not been determined as of commit date.
|
||||
|
||||
|
||||
@@ -122,6 +122,7 @@
|
||||
if(!ps.load_from_json(query_info.m_body)) \
|
||||
{ \
|
||||
boost::value_initialized<epee::json_rpc::error_response> rsp; \
|
||||
static_cast<epee::json_rpc::error_response&>(rsp).jsonrpc = "2.0"; \
|
||||
static_cast<epee::json_rpc::error_response&>(rsp).error.code = -32700; \
|
||||
static_cast<epee::json_rpc::error_response&>(rsp).error.message = "Parse error"; \
|
||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
|
||||
|
||||
@@ -35,6 +35,11 @@
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template<class C> void hint_resize(C &container, size_t size) {}
|
||||
template<class C> void hint_resize(std::vector<C> &container, size_t size) { container.reserve(size); }
|
||||
}
|
||||
namespace serialization
|
||||
{
|
||||
|
||||
@@ -158,6 +163,7 @@ namespace epee
|
||||
false,
|
||||
"size in blob " << loaded_size << " not have not zero modulo for sizeof(value_type) = " << sizeof(typename stl_container::value_type));
|
||||
size_t count = (loaded_size/sizeof(typename stl_container::value_type));
|
||||
hint_resize(container, count);
|
||||
for(size_t i = 0; i < count; i++)
|
||||
container.insert(container.end(), *(pelem++));
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace misc_utils
|
||||
@@ -36,8 +38,12 @@ namespace misc_utils
|
||||
{
|
||||
inline std::string transform_to_escape_sequence(const std::string& src)
|
||||
{
|
||||
//std::stringstream res;
|
||||
static const char escaped[] = "\b\f\n\r\t\v\"\\/";
|
||||
if (std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped)) == src.end())
|
||||
return src;
|
||||
|
||||
std::string res;
|
||||
res.reserve(2 * src.size());
|
||||
for(std::string::const_iterator it = src.begin(); it!=src.end(); ++it)
|
||||
{
|
||||
switch(*it)
|
||||
@@ -84,6 +90,7 @@ namespace misc_utils
|
||||
inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
|
||||
{
|
||||
val.clear();
|
||||
val.reserve(std::distance(star_end_string, buf_end));
|
||||
bool escape_mode = false;
|
||||
std::string::const_iterator it = star_end_string;
|
||||
++it;
|
||||
|
||||
2
external/unbound
vendored
2
external/unbound
vendored
Submodule external/unbound updated: 193bdc4ee3...7f23967954
Binary file not shown.
@@ -185,7 +185,13 @@ namespace cryptonote
|
||||
ADD_CHECKPOINT(20000, "52cc7edcb49eb02f28a653b824089a726f4050eb210263ee6f4180d388a1e5cc");
|
||||
ADD_CHECKPOINT(30000, "d22fde5dd240ade16d3250eb0aa5d1c16dc7cb51c20484e05eb274911032b3fa");
|
||||
ADD_CHECKPOINT(40000, "aee0d642322542ba069cb1c58ab2acd3560f108d4682c3dc3cb15a54d442d91f");
|
||||
ADD_CHECKPOINT(50000, "5286ac2a0f39b3aefcba363cd71f2760bd1e0d763cbc81026ebdc3f80a86541f");
|
||||
ADD_CHECKPOINT(50000, "5286ac2a0f39b3aefcba363cd71f2760bd1e0d763cbc81026ebdc3f80a86541f");
|
||||
ADD_CHECKPOINT(53666, "3f43f56f66ef0c43cf2fd14d0d28fa2aae0ef8f40716773511345750770f1255"); //Hard fork to v9
|
||||
ADD_CHECKPOINT(54500, "8ed3078b389c2b44add007803d741b58d3fbed2e1ba4139bda702152d8773c9b");
|
||||
ADD_CHECKPOINT(55000, "4b662ceccefc3247edb4d654dd610b8fb496e85b88a5de43cc2bdd28171b15ff");
|
||||
ADD_CHECKPOINT(57000, "08a79f09f12bb5d230b63963356a760d51618e526cfc636047a6f3798217c177");
|
||||
ADD_CHECKPOINT(59000, "180b51ee2c5fbcd4362eb7a29df9422481310dd77d10bccdf8930724c31e007e");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -201,15 +201,25 @@ namespace cryptonote
|
||||
{
|
||||
crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation);
|
||||
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
|
||||
if (!r)
|
||||
{
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
|
||||
memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
|
||||
}
|
||||
|
||||
std::vector<crypto::key_derivation> additional_recv_derivations;
|
||||
for (size_t i = 0; i < additional_tx_public_keys.size(); ++i)
|
||||
{
|
||||
crypto::key_derivation additional_recv_derivation = AUTO_VAL_INIT(additional_recv_derivation);
|
||||
r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
|
||||
CHECK_AND_ASSERT_MES(r, false, "key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
|
||||
additional_recv_derivations.push_back(additional_recv_derivation);
|
||||
if (!r)
|
||||
{
|
||||
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
additional_recv_derivations.push_back(additional_recv_derivation);
|
||||
}
|
||||
}
|
||||
|
||||
boost::optional<subaddress_receive_info> subaddr_recv_info = is_out_to_acc_precomp(subaddresses, out_key, recv_derivation, additional_recv_derivations, real_output_index,hwdev);
|
||||
|
||||
@@ -256,14 +256,10 @@ namespace cryptonote {
|
||||
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= static_cast<uint64_t>(N+1) );
|
||||
|
||||
if ( cryptonote::MAINNET && height <= DIFFICULTY_HEIGHT ){
|
||||
if ( height <= DIFFICULTY_HEIGHT ){
|
||||
return static_cast<uint64_t>(DIFFICULTY_GUESS);
|
||||
}
|
||||
|
||||
if ( cryptonote::TESTNET && height <= DIFFICULTY_TESTNET_HEIGHT ){
|
||||
return static_cast<uint64_t>(DIFFICULTY_TESTNET_GUESS);
|
||||
}
|
||||
|
||||
for ( int64_t i = 1; i <= N; i++ ) {
|
||||
ST = static_cast<int64_t>(timestamps[i]) - static_cast<int64_t>(timestamps[i-1]);
|
||||
ST = std::max(-4*T, std::min(ST, 6*T));
|
||||
@@ -281,14 +277,50 @@ namespace cryptonote {
|
||||
next_D = std::max(next_D,(prev_D*108)/100);
|
||||
}
|
||||
|
||||
if ( cryptonote::MAINNET && next_D < DIFFICULTY_MINIMUM ) {
|
||||
if ( next_D < DIFFICULTY_MINIMUM ) {
|
||||
return static_cast<uint64_t>(DIFFICULTY_MINIMUM);
|
||||
}
|
||||
else if ( cryptonote::TESTNET && next_D < DIFFICULTY_TESTNET_MINIMUM ) {
|
||||
return static_cast<uint64_t>(DIFFICULTY_TESTNET_MINIMUM);
|
||||
}
|
||||
else {
|
||||
return static_cast<uint64_t>(next_D);
|
||||
}
|
||||
}
|
||||
|
||||
// LWMA-3 difficulty algorithm
|
||||
// Copyright (c) 2017-2018 Zawy, MIT License
|
||||
difficulty_type next_difficulty_v4(std::vector<uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t height) {
|
||||
|
||||
uint64_t T = DIFFICULTY_TARGET_V2;
|
||||
uint64_t N = DIFFICULTY_WINDOW_V2;
|
||||
uint64_t L(0), ST, sum_3_ST(0), next_D, prev_D, this_timestamp, previous_timestamp;
|
||||
|
||||
assert(timestamps.size() == cumulative_difficulties.size() && timestamps.size() <= N+1 );
|
||||
|
||||
if ( height == DIFFICULTY_HEIGHT_V2 ){
|
||||
return static_cast<uint64_t>(DIFFICULTY_GUESS);
|
||||
}
|
||||
|
||||
previous_timestamp = timestamps[0];
|
||||
for ( uint64_t i = 1; i <= N; i++) {
|
||||
if ( timestamps[i] > previous_timestamp ) {
|
||||
this_timestamp = timestamps[i];
|
||||
} else { this_timestamp = previous_timestamp+1; }
|
||||
ST = std::min(6*T ,this_timestamp - previous_timestamp);
|
||||
previous_timestamp = this_timestamp;
|
||||
L += ST * i ;
|
||||
if ( i > N-3 ) { sum_3_ST += ST; }
|
||||
}
|
||||
|
||||
next_D = ((cumulative_difficulties[N] - cumulative_difficulties[0])*T*(N+1)*99)/(100*2*L);
|
||||
prev_D = cumulative_difficulties[N] - cumulative_difficulties[N-1];
|
||||
next_D = std::max((prev_D*67)/100, std::min(next_D, (prev_D*150)/100));
|
||||
|
||||
if ( sum_3_ST < (8*T)/10) { next_D = std::max(next_D,(prev_D*108)/100); }
|
||||
|
||||
if ( next_D < DIFFICULTY_MINIMUM ) {
|
||||
return static_cast<uint64_t>(DIFFICULTY_MINIMUM);
|
||||
}
|
||||
else {
|
||||
return static_cast<uint64_t>(next_D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,4 +55,5 @@ namespace cryptonote
|
||||
difficulty_type next_difficulty(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||
difficulty_type next_difficulty_v2(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t target_seconds);
|
||||
difficulty_type next_difficulty_v3(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t height);
|
||||
difficulty_type next_difficulty_v4(std::vector<std::uint64_t> timestamps, std::vector<difficulty_type> cumulative_difficulties, size_t height);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2
|
||||
#define CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE 4
|
||||
|
||||
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 11
|
||||
#define BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW 60
|
||||
|
||||
// MONEY_SUPPLY - total number coins to be generated
|
||||
@@ -82,11 +83,9 @@
|
||||
#define DIFFICULTY_BLOCKS_COUNT_V2 DIFFICULTY_WINDOW_V2 + 1 // added +1 to make N=N
|
||||
#define DIFFICULTY_BLOCKS_COUNT DIFFICULTY_WINDOW + DIFFICULTY_LAG
|
||||
#define DIFFICULTY_HEIGHT 53666 // v9 fork height
|
||||
#define DIFFICULTY_HEIGHT_V2 777777 // v10 fork height
|
||||
#define DIFFICULTY_GUESS 40000000 // difficulty at fork 40m
|
||||
#define DIFFICULTY_MINIMUM 10000000 // minimum difficulty set to 10m
|
||||
#define DIFFICULTY_TESTNET_HEIGHT 100
|
||||
#define DIFFICULTY_TESTNET_GUESS 5069
|
||||
#define DIFFICULTY_TESTNET_MINIMUM 4069
|
||||
#define DIFFICULTY_MINIMUM 25000000 // minimum difficulty set to 25m
|
||||
|
||||
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V1 DIFFICULTY_TARGET_V1 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
|
||||
#define CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_SECONDS_V2 DIFFICULTY_TARGET_V2 * CRYPTONOTE_LOCKED_TX_ALLOWED_DELTA_BLOCKS
|
||||
|
||||
@@ -838,8 +838,11 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
|
||||
else if (version == 8) {
|
||||
return next_difficulty_v2(timestamps, difficulties, target);
|
||||
}
|
||||
else {
|
||||
else if (version == 9) {
|
||||
return next_difficulty_v3(timestamps, difficulties, height);
|
||||
}
|
||||
else {
|
||||
return next_difficulty_v4(timestamps, difficulties, height);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
@@ -1056,9 +1059,12 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
|
||||
}
|
||||
else if (version == 8) {
|
||||
return next_difficulty_v2(timestamps, cumulative_difficulties, target);
|
||||
}
|
||||
}
|
||||
else if (version == 9) {
|
||||
return next_difficulty_v2(timestamps, cumulative_difficulties, height);
|
||||
}
|
||||
else {
|
||||
return next_difficulty_v3(timestamps, cumulative_difficulties, height);
|
||||
return next_difficulty_v4(timestamps, cumulative_difficulties, height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1350,12 +1356,13 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
||||
bool Blockchain::complete_timestamps_vector(uint64_t start_top_height, std::vector<uint64_t>& timestamps)
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
|
||||
if(timestamps.size() >= BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
size_t blockchain_timestamp_check_window = hf_version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
|
||||
if(timestamps.size() >= blockchain_timestamp_check_window)
|
||||
return true;
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||
size_t need_elements = BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW - timestamps.size();
|
||||
size_t need_elements = blockchain_timestamp_check_window - timestamps.size();
|
||||
CHECK_AND_ASSERT_MES(start_top_height < m_db->height(), false, "internal error: passed start_height not < " << " m_db->height() -- " << start_top_height << " >= " << m_db->height());
|
||||
size_t stop_offset = start_top_height > need_elements ? start_top_height - need_elements : 0;
|
||||
while (start_top_height != stop_offset)
|
||||
@@ -3203,10 +3210,12 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
median_ts = epee::misc_utils::median(timestamps);
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
size_t blockchain_timestamp_check_window = hf_version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
|
||||
|
||||
if(b.timestamp < median_ts)
|
||||
{
|
||||
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
|
||||
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << blockchain_timestamp_check_window << " blocks, " << median_ts);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3224,6 +3233,8 @@ bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) cons
|
||||
{
|
||||
LOG_PRINT_L3("Blockchain::" << __func__);
|
||||
uint64_t cryptonote_block_future_time_limit = get_current_hard_fork_version() >= 8 ? CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT_V2 : CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT;
|
||||
const uint8_t hf_version = m_hardfork->get_current_version();
|
||||
size_t blockchain_timestamp_check_window = hf_version >= 10 ? BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW_V2 : BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
|
||||
if(b.timestamp > get_adjusted_time() + cryptonote_block_future_time_limit)
|
||||
{
|
||||
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 10 minutes");
|
||||
@@ -3231,7 +3242,7 @@ bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) cons
|
||||
}
|
||||
|
||||
// if not enough blocks, no proper median yet, return true
|
||||
if(m_db->height() < BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)
|
||||
if(m_db->height() < blockchain_timestamp_check_window)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -3240,7 +3251,7 @@ bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) cons
|
||||
auto h = m_db->height();
|
||||
|
||||
// need most recent 60 blocks, get index of first of those
|
||||
size_t offset = h - BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW;
|
||||
size_t offset = h - blockchain_timestamp_check_window;
|
||||
for(;offset < h; ++offset)
|
||||
{
|
||||
timestamps.push_back(m_db->get_block_timestamp(offset));
|
||||
@@ -4441,7 +4452,7 @@ void Blockchain::cancel()
|
||||
}
|
||||
|
||||
#if defined(PER_BLOCK_CHECKPOINT)
|
||||
static const char expected_block_hashes_hash[] = "16cb7e839284c1910925f8d9f8a752f38ad908ae9deec7afdfbbc4a777f5ef2e";
|
||||
static const char expected_block_hashes_hash[] = "897d3ae0f3aef8ef8362b0bb3535925738414fa78d9146f8a04c60555fa5a95f";
|
||||
void Blockchain::load_compiled_in_block_hashes()
|
||||
{
|
||||
const bool testnet = m_nettype == TESTNET;
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace cryptonote
|
||||
out_amounts[1] += out_amounts[0];
|
||||
for (size_t n = 1; n < out_amounts.size(); ++n)
|
||||
out_amounts[n - 1] = out_amounts[n];
|
||||
out_amounts.resize(out_amounts.size() - 1);
|
||||
out_amounts.pop_back();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1095,7 +1095,7 @@ namespace cryptonote
|
||||
LockedTXN lock(m_blockchain);
|
||||
|
||||
auto sorted_it = m_txs_by_fee_and_receive_time.begin();
|
||||
while (sorted_it != m_txs_by_fee_and_receive_time.end())
|
||||
for (; sorted_it != m_txs_by_fee_and_receive_time.end(); ++sorted_it)
|
||||
{
|
||||
txpool_tx_meta_t meta;
|
||||
if (!m_blockchain.get_txpool_tx_meta(sorted_it->second, meta))
|
||||
@@ -1109,7 +1109,6 @@ namespace cryptonote
|
||||
if (max_total_size < total_size + meta.blob_size)
|
||||
{
|
||||
LOG_PRINT_L2(" would exceed maximum block size");
|
||||
sorted_it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1122,14 +1121,12 @@ namespace cryptonote
|
||||
if(!get_block_reward(median_size, total_size + meta.blob_size, already_generated_coins, block_reward, version))
|
||||
{
|
||||
LOG_PRINT_L2(" would exceed maximum block size");
|
||||
sorted_it++;
|
||||
continue;
|
||||
}
|
||||
coinbase = block_reward + fee + meta.fee;
|
||||
if (coinbase < template_accept_threshold(best_coinbase))
|
||||
{
|
||||
LOG_PRINT_L2(" would decrease coinbase to " << print_money(coinbase));
|
||||
sorted_it++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1173,13 +1170,11 @@ namespace cryptonote
|
||||
if (!ready)
|
||||
{
|
||||
LOG_PRINT_L2(" not ready to go");
|
||||
sorted_it++;
|
||||
continue;
|
||||
}
|
||||
if (have_key_images(k_images, tx))
|
||||
{
|
||||
LOG_PRINT_L2(" key images already seen");
|
||||
sorted_it++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1188,7 +1183,6 @@ namespace cryptonote
|
||||
fee += meta.fee;
|
||||
best_coinbase = coinbase;
|
||||
append_key_images(k_images, tx);
|
||||
sorted_it++;
|
||||
LOG_PRINT_L2(" added, new block size " << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase));
|
||||
}
|
||||
|
||||
@@ -1284,6 +1278,7 @@ namespace cryptonote
|
||||
{
|
||||
MWARNING("Failed to parse tx from txpool, removing");
|
||||
remove.push_back(txid);
|
||||
return true;
|
||||
}
|
||||
if (!insert_key_images(tx, meta.kept_by_block))
|
||||
{
|
||||
|
||||
@@ -1167,8 +1167,20 @@ skip:
|
||||
+ " blocks/sec), " + std::to_string(m_block_queue.get_data_size() / 1048576.f) + " MB queued";
|
||||
if (ELPP->vRegistry()->allowed(el::Level::Debug, "sync-info"))
|
||||
timing_message += std::string(": ") + m_block_queue.get_overview();
|
||||
MGINFO_YELLOW(context << " Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height()
|
||||
if(m_core.get_target_blockchain_height() == 0){
|
||||
MGINFO_YELLOW(context << " Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height()
|
||||
<< timing_message);
|
||||
} else {
|
||||
const int completition_percent = (m_core.get_current_blockchain_height() * 100 / m_core.get_target_blockchain_height());
|
||||
if(completition_percent < 99) {//printing completion percent only if % is < of 99 cause for 99 >= this is useless
|
||||
MGINFO_YELLOW(context << " Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height()
|
||||
<< " (" << completition_percent << "% " << (m_core.get_target_blockchain_height() - m_core.get_current_blockchain_height())
|
||||
<< " blocks remaining)" << timing_message);
|
||||
} else {
|
||||
MGINFO_YELLOW(context << " Synced " << m_core.get_current_blockchain_height() << "/" << m_core.get_target_blockchain_height()
|
||||
<< timing_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1752,3 +1764,4 @@ skip:
|
||||
m_core.stop();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
||||
@@ -661,7 +661,7 @@ bool t_command_parser_executor::sync_info(const std::vector<std::string>& args)
|
||||
|
||||
bool t_command_parser_executor::version(const std::vector<std::string>& args)
|
||||
{
|
||||
std::cout << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
|
||||
std::cout << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +438,8 @@ bool t_rpc_command_executor::show_status() {
|
||||
}
|
||||
}
|
||||
|
||||
tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections, uptime %ud %uh %um %us")
|
||||
std::stringstream str;
|
||||
str << boost::format("Height: %llu/%llu (%.1f%%) on %s%s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections")
|
||||
% (unsigned long long)ires.height
|
||||
% (unsigned long long)net_height
|
||||
% get_sync_percentage(ires)
|
||||
@@ -451,12 +452,21 @@ bool t_rpc_command_executor::show_status() {
|
||||
% (hfres.state == cryptonote::HardFork::Ready ? "up to date" : hfres.state == cryptonote::HardFork::UpdateNeeded ? "update needed" : "out of date, likely forked")
|
||||
% (unsigned)ires.outgoing_connections_count
|
||||
% (unsigned)ires.incoming_connections_count
|
||||
% (unsigned int)floor(uptime / 60.0 / 60.0 / 24.0)
|
||||
% (unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0))
|
||||
% (unsigned int)floor(fmod((uptime / 60.0), 60.0))
|
||||
% (unsigned int)fmod(uptime, 60.0)
|
||||
;
|
||||
|
||||
// restricted RPC does not disclose start time
|
||||
if (ires.start_time)
|
||||
{
|
||||
str << boost::format(", uptime %ud %uh %um %us")
|
||||
% (unsigned int)floor(uptime / 60.0 / 60.0 / 24.0)
|
||||
% (unsigned int)floor(fmod((uptime / 60.0 / 60.0), 24.0))
|
||||
% (unsigned int)floor(fmod((uptime / 60.0), 60.0))
|
||||
% (unsigned int)fmod(uptime, 60.0)
|
||||
;
|
||||
}
|
||||
|
||||
tools::success_msg_writer() << str.str();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -554,7 +564,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u
|
||||
if (!first)
|
||||
std::cout << std::endl;
|
||||
std::cout
|
||||
<< "height: " << header.height << ", timestamp: " << header.timestamp << ", difficulty: " << header.difficulty
|
||||
<< "height: " << header.height << ", timestamp: " << header.timestamp
|
||||
<< ", size: " << header.block_size << ", transactions: " << header.num_txes << std::endl
|
||||
<< "major version: " << (unsigned)header.major_version << ", minor version: " << (unsigned)header.minor_version << std::endl
|
||||
<< "block id: " << header.hash << ", previous block id: " << header.prev_hash << std::endl
|
||||
|
||||
@@ -863,7 +863,13 @@ namespace cryptonote
|
||||
boost::thread::attributes attrs;
|
||||
attrs.set_stack_size(THREAD_STACK_SIZE);
|
||||
|
||||
if(!m_core.get_miner().start(info.address, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining, req.ignore_battery))
|
||||
cryptonote::miner &miner= m_core.get_miner();
|
||||
if (miner.is_mining())
|
||||
{
|
||||
res.status = "Already mining";
|
||||
return true;
|
||||
}
|
||||
if(!miner.start(info.address, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining, req.ignore_battery))
|
||||
{
|
||||
res.status = "Failed, mining not started";
|
||||
LOG_PRINT_L0(res.status);
|
||||
@@ -992,6 +998,8 @@ namespace cryptonote
|
||||
return r;
|
||||
|
||||
m_core.get_pool_transactions_and_spent_keys_info(res.transactions, res.spent_key_images, !request_has_rpc_origin || !m_restricted);
|
||||
for (tx_info& txi : res.transactions)
|
||||
txi.tx_blob = epee::string_tools::buff_to_hex_nodelimer(txi.tx_blob);
|
||||
res.status = CORE_RPC_STATUS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -93,13 +93,8 @@ typedef cryptonote::simple_wallet sw;
|
||||
m_auto_refresh_enabled.store(false, std::memory_order_relaxed); \
|
||||
/* stop any background refresh, and take over */ \
|
||||
m_wallet->stop(); \
|
||||
m_idle_mutex.lock(); \
|
||||
while (m_auto_refresh_refreshing) \
|
||||
m_idle_cond.notify_one(); \
|
||||
m_idle_mutex.unlock(); \
|
||||
/* if (auto_refresh_run)*/ \
|
||||
/*m_auto_refresh_thread.join();*/ \
|
||||
boost::unique_lock<boost::mutex> lock(m_idle_mutex); \
|
||||
m_idle_cond.notify_all(); \
|
||||
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ \
|
||||
m_auto_refresh_enabled.store(auto_refresh_enabled, std::memory_order_relaxed); \
|
||||
})
|
||||
@@ -525,6 +520,18 @@ bool parse_priority(const std::string& arg, uint32_t& priority)
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string join_priority_strings(const char *delimiter)
|
||||
{
|
||||
std::string s;
|
||||
for (size_t n = 0; n < allowed_priority_strings.size(); ++n)
|
||||
{
|
||||
if (!s.empty())
|
||||
s += delimiter;
|
||||
s += allowed_priority_strings[n];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string simple_wallet::get_commands_str()
|
||||
{
|
||||
std::stringstream ss;
|
||||
@@ -1560,7 +1567,7 @@ bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
|
||||
|
||||
bool simple_wallet::version(const std::vector<std::string> &args)
|
||||
{
|
||||
message_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
|
||||
message_writer() << "Wownero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1611,12 +1618,12 @@ bool simple_wallet::set_store_tx_info(const std::vector<std::string> &args/* = s
|
||||
|
||||
bool simple_wallet::set_default_priority(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
{
|
||||
int priority = 0;
|
||||
uint32_t priority = 0;
|
||||
try
|
||||
{
|
||||
if (strchr(args[1].c_str(), '-'))
|
||||
{
|
||||
fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4 ");
|
||||
fail_msg_writer() << tr("priority must be either 0, 1, 2, 3, or 4, or one of: ") << join_priority_strings(", ");
|
||||
return true;
|
||||
}
|
||||
if (args[1] == "0")
|
||||
@@ -1625,11 +1632,23 @@ bool simple_wallet::set_default_priority(const std::vector<std::string> &args/*
|
||||
}
|
||||
else
|
||||
{
|
||||
priority = boost::lexical_cast<int>(args[1]);
|
||||
if (priority < 1 || priority > 4)
|
||||
bool found = false;
|
||||
for (size_t n = 0; n < allowed_priority_strings.size(); ++n)
|
||||
{
|
||||
fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4");
|
||||
return true;
|
||||
if (allowed_priority_strings[n] == args[1])
|
||||
{
|
||||
found = true;
|
||||
priority = n;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
priority = boost::lexical_cast<int>(args[1]);
|
||||
if (priority < 1 || priority > 4)
|
||||
{
|
||||
fail_msg_writer() << tr("priority must be either 0, 1, 2, 3, or 4, or one of: ") << join_priority_strings(", ");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1643,7 +1662,7 @@ bool simple_wallet::set_default_priority(const std::vector<std::string> &args/*
|
||||
}
|
||||
catch(const boost::bad_lexical_cast &)
|
||||
{
|
||||
fail_msg_writer() << tr("priority must be 0, 1, 2, 3, or 4");
|
||||
fail_msg_writer() << tr("priority must be either 0, 1, 2, 3, or 4, or one of: ") << join_priority_strings(", ");
|
||||
return true;
|
||||
}
|
||||
catch(...)
|
||||
@@ -1688,13 +1707,13 @@ bool simple_wallet::set_refresh_type(const std::vector<std::string> &args/* = st
|
||||
return true;
|
||||
}
|
||||
|
||||
bool simple_wallet::set_confirm_missing_payment_id(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
bool simple_wallet::set_confirm_subaddress(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
{
|
||||
const auto pwd_container = get_and_verify_password();
|
||||
if (pwd_container)
|
||||
{
|
||||
parse_bool_and_use(args[1], [&](bool r) {
|
||||
m_wallet->confirm_missing_payment_id(r);
|
||||
m_wallet->confirm_subaddress(r);
|
||||
m_wallet->rewrite(m_wallet_file, pwd_container->password());
|
||||
});
|
||||
}
|
||||
@@ -1931,10 +1950,10 @@ bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<st
|
||||
"Commands:\n" <<
|
||||
tr(" \"balance\" - Show balance.\n") <<
|
||||
tr(" \"address\" - Show wallet's address.\n") <<
|
||||
tr(" \"integrated_address\" - Show receiving address with an integrated payment ID.\n") <<
|
||||
tr(" \"transfer [address|integrated_address] [amount]\" - Send WOW to an address.\n") <<
|
||||
tr(" \"address new [optional note]\" - Create new sub-address with optional note, spaces are allowed.\n") <<
|
||||
tr(" \"address all\" - Show all sub-addresses.\n") <<
|
||||
tr(" \"transfer [address] [amount]\" - Send WOW to an address.\n") <<
|
||||
tr(" \"show_transfers [in|out|pending|failed|pool]\" - Show transactions.\n") <<
|
||||
tr(" \"payments [payment ID]\" - Show transaction of a given payment ID.\n") <<
|
||||
tr(" \"sweep_all [address]\" - Send whole balance to another wallet.\n") <<
|
||||
tr(" \"seed\" - Show secret 25 words that can be used to recover this wallet.\n") <<
|
||||
tr(" \"refresh\" - Synchronize wallet with the Wownero network.\n") <<
|
||||
@@ -2064,13 +2083,9 @@ simple_wallet::simple_wallet()
|
||||
boost::bind(&simple_wallet::print_address, this, _1),
|
||||
tr("address [ new <label text with white spaces allowed> | all | <index_min> [<index_max>] | label <index> <label text with white spaces allowed>]"),
|
||||
tr("If no arguments are specified or <index> is specified, the wallet shows the default or specified address. If \"all\" is specified, the wallet shows all the existing addresses in the currently selected account. If \"new \" is specified, the wallet creates a new address with the provided label text (which can be empty). If \"label\" is specified, the wallet sets the label of the address specified by <index> to the provided label text."));
|
||||
m_cmd_binder.set_handler("integrated_address",
|
||||
boost::bind(&simple_wallet::print_integrated_address, this, _1),
|
||||
tr("integrated_address [<payment_id> | <address>]"),
|
||||
tr("Encode a payment ID into an integrated address for the current wallet public address (no argument uses a random payment ID), or decode an integrated address to standard address and payment ID"));
|
||||
m_cmd_binder.set_handler("address_book",
|
||||
boost::bind(&simple_wallet::address_book, this, _1),
|
||||
tr("address_book [(add ((<address> [pid <id>])|<integrated address>) [<description possibly with whitespaces>])|(delete <index>)]"),
|
||||
tr("address_book [(add ((<address> [pid <id>])) [<description possibly with whitespaces>])|(delete <index>)]"),
|
||||
tr("Print all entries in the address book, optionally adding/deleting an entry to/from it."));
|
||||
m_cmd_binder.set_handler("save",
|
||||
boost::bind(&simple_wallet::save, this, _1),
|
||||
@@ -2182,7 +2197,7 @@ simple_wallet::simple_wallet()
|
||||
tr("Show the unspent outputs of a specified address within an optional amount range."));
|
||||
m_cmd_binder.set_handler("rescan_bc",
|
||||
boost::bind(&simple_wallet::rescan_blockchain, this, _1),
|
||||
tr("Rescan the blockchain from scratch."));
|
||||
tr("Rescan the blockchain from scratch, losing any information which can not be recovered from the blockchain itself."));
|
||||
m_cmd_binder.set_handler("set_tx_note",
|
||||
boost::bind(&simple_wallet::set_tx_note, this, _1),
|
||||
tr("set_tx_note <txid> [free text note]"),
|
||||
@@ -2312,6 +2327,10 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
|
||||
std::string seed_language = m_wallet->get_seed_language();
|
||||
if (m_use_english_language_names)
|
||||
seed_language = crypto::ElectrumWords::get_english_name_for(seed_language);
|
||||
std::string priority_string = "invalid";
|
||||
uint32_t priority = m_wallet->get_default_priority();
|
||||
if (priority < allowed_priority_strings.size())
|
||||
priority_string = allowed_priority_strings[priority];
|
||||
success_msg_writer() << "seed = " << seed_language;
|
||||
success_msg_writer() << "always-confirm-transfers = " << m_wallet->always_confirm_transfers();
|
||||
success_msg_writer() << "print-ring-members = " << m_wallet->print_ring_members();
|
||||
@@ -2319,7 +2338,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
|
||||
success_msg_writer() << "auto-refresh = " << m_wallet->auto_refresh();
|
||||
success_msg_writer() << "refresh-type = " << get_refresh_type_name(m_wallet->get_refresh_type());
|
||||
success_msg_writer() << "priority = " << m_wallet->get_default_priority();
|
||||
success_msg_writer() << "confirm-missing-payment-id = " << m_wallet->confirm_missing_payment_id();
|
||||
success_msg_writer() << "confirm-subaddress = " << m_wallet->confirm_subaddress();
|
||||
success_msg_writer() << "ask-password = " << m_wallet->ask_password();
|
||||
success_msg_writer() << "unit = " << cryptonote::get_unit(cryptonote::get_default_decimal_point());
|
||||
success_msg_writer() << "min-outputs-count = " << m_wallet->get_min_output_count();
|
||||
@@ -2373,7 +2392,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
|
||||
CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1"));
|
||||
CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)"));
|
||||
CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4"));
|
||||
CHECK_SIMPLE_VARIABLE("confirm-missing-payment-id", set_confirm_missing_payment_id, tr("0 or 1"));
|
||||
CHECK_SIMPLE_VARIABLE("confirm-subaddress", set_confirm_subaddress, tr("0 or 1"));
|
||||
CHECK_SIMPLE_VARIABLE("ask-password", set_ask_password, tr("0 or 1"));
|
||||
CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("wownero, millinero, micronero, nanonero, piconero"));
|
||||
CHECK_SIMPLE_VARIABLE("min-outputs-count", set_min_output_count, tr("unsigned integer"));
|
||||
@@ -2631,6 +2650,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
m_recovery_key = cryptonote::decrypt_key(m_recovery_key, seed_pass);
|
||||
}
|
||||
}
|
||||
epee::wipeable_string password;
|
||||
if (!m_generate_from_view_key.empty())
|
||||
{
|
||||
m_wallet_file = m_generate_from_view_key;
|
||||
@@ -2683,8 +2703,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool r = new_wallet(vm, info.address, boost::none, viewkey);
|
||||
auto r = new_wallet(vm, info.address, boost::none, viewkey);
|
||||
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
|
||||
password = *r;
|
||||
}
|
||||
else if (!m_generate_from_spend_key.empty())
|
||||
{
|
||||
@@ -2702,8 +2723,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
fail_msg_writer() << tr("failed to parse spend key secret key");
|
||||
return false;
|
||||
}
|
||||
bool r = new_wallet(vm, m_recovery_key, true, false, "");
|
||||
auto r = new_wallet(vm, m_recovery_key, true, false, "");
|
||||
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
|
||||
password = *r;
|
||||
}
|
||||
else if (!m_generate_from_keys.empty())
|
||||
{
|
||||
@@ -2780,8 +2802,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
fail_msg_writer() << tr("view key does not match standard address");
|
||||
return false;
|
||||
}
|
||||
bool r = new_wallet(vm, info.address, spendkey, viewkey);
|
||||
auto r = new_wallet(vm, info.address, spendkey, viewkey);
|
||||
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
|
||||
password = *r;
|
||||
}
|
||||
|
||||
// Asks user for all the data required to merge secret keys from multisig wallets into one master wallet, which then gets full control of the multisig wallet. The resulting wallet will be the same as any other regular wallet.
|
||||
@@ -2914,8 +2937,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
}
|
||||
|
||||
// create wallet
|
||||
bool r = new_wallet(vm, info.address, spendkey, viewkey);
|
||||
auto r = new_wallet(vm, info.address, spendkey, viewkey);
|
||||
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
|
||||
password = *r;
|
||||
}
|
||||
|
||||
else if (!m_generate_from_json.empty())
|
||||
@@ -2937,8 +2961,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
{
|
||||
m_wallet_file = m_generate_from_device;
|
||||
// create wallet
|
||||
bool r = new_wallet(vm, "Ledger");
|
||||
auto r = new_wallet(vm, "Ledger");
|
||||
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
|
||||
password = *r;
|
||||
// if no block_height is specified, assume its a new account and start it "now"
|
||||
if(m_wallet->get_refresh_from_block_height() == 0) {
|
||||
{
|
||||
@@ -2963,12 +2988,13 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
return false;
|
||||
}
|
||||
m_wallet_file = m_generate_new;
|
||||
bool r;
|
||||
boost::optional<epee::wipeable_string> r;
|
||||
if (m_restore_multisig_wallet)
|
||||
r = new_wallet(vm, multisig_keys, old_language);
|
||||
else
|
||||
r = new_wallet(vm, m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic, old_language);
|
||||
CHECK_AND_ASSERT_MES(r, false, tr("account creation failed"));
|
||||
password = *r;
|
||||
}
|
||||
|
||||
if (m_restoring && m_generate_from_json.empty() && m_generate_from_device.empty())
|
||||
@@ -3050,6 +3076,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||
}
|
||||
m_wallet->set_refresh_from_block_height(m_restore_height);
|
||||
}
|
||||
m_wallet->rewrite(m_wallet_file, password);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3217,15 +3244,16 @@ boost::optional<tools::password_container> simple_wallet::get_and_verify_passwor
|
||||
return pwd_container;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
const crypto::secret_key& recovery_key, bool recover, bool two_random, const std::string &old_language)
|
||||
{
|
||||
auto rc = tools::wallet2::make_new(vm, password_prompter);
|
||||
m_wallet = std::move(rc.first);
|
||||
if (!m_wallet)
|
||||
{
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
epee::wipeable_string password = rc.second.password();
|
||||
|
||||
if (!m_subaddress_lookahead.empty())
|
||||
{
|
||||
@@ -3261,7 +3289,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
}
|
||||
mnemonic_language = get_mnemonic_language();
|
||||
if (mnemonic_language.empty())
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
m_wallet->set_seed_language(mnemonic_language);
|
||||
@@ -3279,7 +3307,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fail_msg_writer() << tr("failed to generate new wallet: ") << e.what();
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
// convert rng value to electrum-style word list
|
||||
@@ -3305,10 +3333,10 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
}
|
||||
success_msg_writer() << "**********************************************************************";
|
||||
|
||||
return true;
|
||||
return std::move(password);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
const cryptonote::account_public_address& address, const boost::optional<crypto::secret_key>& spendkey,
|
||||
const crypto::secret_key& viewkey)
|
||||
{
|
||||
@@ -3316,8 +3344,9 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
m_wallet = std::move(rc.first);
|
||||
if (!m_wallet)
|
||||
{
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
epee::wipeable_string password = rc.second.password();
|
||||
|
||||
if (!m_subaddress_lookahead.empty())
|
||||
{
|
||||
@@ -3347,22 +3376,23 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fail_msg_writer() << tr("failed to generate new wallet: ") << e.what();
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
return std::move(password);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
const std::string &device_name) {
|
||||
auto rc = tools::wallet2::make_new(vm, password_prompter);
|
||||
m_wallet = std::move(rc.first);
|
||||
if (!m_wallet)
|
||||
{
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
epee::wipeable_string password = rc.second.password();
|
||||
|
||||
if (!m_subaddress_lookahead.empty())
|
||||
{
|
||||
@@ -3383,21 +3413,22 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fail_msg_writer() << tr("failed to generate new wallet: ") << e.what();
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
return true;
|
||||
return std::move(password);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
boost::optional<epee::wipeable_string> simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
const std::string &multisig_keys, const std::string &old_language)
|
||||
{
|
||||
auto rc = tools::wallet2::make_new(vm, password_prompter);
|
||||
m_wallet = std::move(rc.first);
|
||||
if (!m_wallet)
|
||||
{
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
epee::wipeable_string password = rc.second.password();
|
||||
|
||||
if (!m_subaddress_lookahead.empty())
|
||||
{
|
||||
@@ -3427,7 +3458,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
if (!m_wallet->multisig(&ready, &threshold, &total) || !ready)
|
||||
{
|
||||
fail_msg_writer() << tr("failed to generate new mutlisig wallet");
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
message_writer(console_color_white, true) << boost::format(tr("Generated new %u/%u multisig wallet: ")) % threshold % total
|
||||
<< m_wallet->get_account().get_public_address_str(m_wallet->nettype());
|
||||
@@ -3435,10 +3466,10 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
fail_msg_writer() << tr("failed to generate new wallet: ") << e.what();
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
|
||||
return true;
|
||||
return std::move(password);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
|
||||
@@ -3470,6 +3501,8 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
|
||||
prefix = tr("Opened wallet");
|
||||
message_writer(console_color_white, true) <<
|
||||
prefix << ": " << m_wallet->get_account().get_public_address_str(m_wallet->nettype());
|
||||
message_writer(console_color_yellow, true) << "\n" << tr("When receiving WOW, "
|
||||
"create a new sub-address for each transaction with the command “address new”. \nUse “address all” to see all sub-addresses.\n");
|
||||
if (m_wallet->get_account().get_device()) {
|
||||
message_writer(console_color_white, true) << "Wallet is on device: " << m_wallet->get_account().get_device().get_name();
|
||||
}
|
||||
@@ -4346,7 +4379,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
std::string extra_nonce;
|
||||
set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
success_msg_writer() << tr("WARNING: Payment id is unencrypted, which might potentially compromise your privacy. An integrated address is recommended instead.\n");
|
||||
success_msg_writer() << tr("\nWARNING: Payment IDs will be deprecated soon. Sub-addresses are recommended instead.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4357,6 +4390,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
std::string extra_nonce;
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id8);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
success_msg_writer() << tr("\nWARNING: Payment IDs will be deprecated soon. Sub-addresses are recommended instead.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4433,10 +4467,10 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
|
||||
dsts.push_back(de);
|
||||
}
|
||||
|
||||
// prompt is there is no payment id and confirmation is required
|
||||
if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && dsts.size() > num_subaddresses)
|
||||
// prompt if regular address
|
||||
if (!payment_id_seen && m_wallet->confirm_subaddress() && dsts.size() > num_subaddresses)
|
||||
{
|
||||
std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
|
||||
std::string accepted = input_line(tr("\nSending to a regular address may degrade privacy. Ask recipient for a sub-address instead. Continue anyway? (Y/Yes/N/No): "));
|
||||
if (std::cin.eof())
|
||||
return true;
|
||||
if (!command_line::is_yes(accepted))
|
||||
@@ -4833,6 +4867,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
|
||||
set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
payment_id_seen = true;
|
||||
success_msg_writer() << tr("\nWARNING: Payment IDs will be deprecated soon. Sub-addresses are recommended instead.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4844,6 +4879,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
|
||||
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id8);
|
||||
r = add_extra_nonce_to_tx_extra(extra, extra_nonce);
|
||||
payment_id_seen = true;
|
||||
success_msg_writer() << tr("\nWARNING: Payment IDs will be deprecated soon. Sub-addresses are recommended instead.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4882,10 +4918,10 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
|
||||
payment_id_seen = true;
|
||||
}
|
||||
|
||||
// prompt is there is no payment id and confirmation is required
|
||||
if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress)
|
||||
// prompt if regular address
|
||||
if (!payment_id_seen && m_wallet->confirm_subaddress() && !info.is_subaddress)
|
||||
{
|
||||
std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
|
||||
std::string accepted = input_line(tr("\nSending to a regular address may degrade privacy. Ask recipient for a sub-address instead. Continue anyway? (Y/Yes/N/No): "));
|
||||
if (std::cin.eof())
|
||||
return true;
|
||||
if (!command_line::is_yes(accepted))
|
||||
@@ -5081,10 +5117,10 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
|
||||
payment_id_seen = true;
|
||||
}
|
||||
|
||||
// prompt if there is no payment id and confirmation is required
|
||||
if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress)
|
||||
// prompt if regular address
|
||||
if (!payment_id_seen && m_wallet->confirm_subaddress() && !info.is_subaddress)
|
||||
{
|
||||
std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
|
||||
std::string accepted = input_line(tr("\nSending to a regular address may degrade privacy. Ask recipient for a sub-address instead. Continue anyway? (Y/Yes/N/No): "));
|
||||
if (std::cin.eof())
|
||||
return true;
|
||||
if (!command_line::is_yes(accepted))
|
||||
@@ -5971,7 +6007,7 @@ static std::string get_human_readable_timespan(std::chrono::seconds seconds)
|
||||
if (ts < 3600 * 24 * 30.5)
|
||||
return std::to_string((uint64_t)(ts / (3600 * 24))) + tr(" days");
|
||||
if (ts < 3600 * 24 * 365.25)
|
||||
return std::to_string((uint64_t)(ts / (3600 * 24 * 365.25))) + tr(" months");
|
||||
return std::to_string((uint64_t)(ts / (3600 * 24 * 30.5))) + tr(" months");
|
||||
return tr("a long time");
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -6167,7 +6203,7 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
|
||||
auto local_args = args_;
|
||||
|
||||
std::set<uint32_t> subaddr_indices;
|
||||
if (local_args.size() > 0 && local_args[0].substr(0, 6) != "index=")
|
||||
if (local_args.size() > 0 && local_args[0].substr(0, 6) == "index=")
|
||||
{
|
||||
if (!parse_subaddress_indices(local_args[0], subaddr_indices))
|
||||
return true;
|
||||
@@ -6297,6 +6333,14 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::rescan_blockchain(const std::vector<std::string> &args_)
|
||||
{
|
||||
message_writer() << tr("Warning: this will lose any information which can not be recovered from the blockchain.");
|
||||
message_writer() << tr("This includes destination addresses, tx secret keys, tx notes, etc");
|
||||
std::string confirm = input_line(tr("Rescan anyway ? (Y/Yes/N/No): "));
|
||||
if(!std::cin.eof())
|
||||
{
|
||||
if (!command_line::is_yes(confirm))
|
||||
return true;
|
||||
}
|
||||
return refresh_main(0, true);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -6675,56 +6719,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool simple_wallet::print_integrated_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
{
|
||||
crypto::hash8 payment_id;
|
||||
if (args.size() > 1)
|
||||
{
|
||||
fail_msg_writer() << tr("usage: integrated_address [payment ID]");
|
||||
return true;
|
||||
}
|
||||
if (args.size() == 0)
|
||||
{
|
||||
if (m_current_subaddress_account != 0)
|
||||
{
|
||||
fail_msg_writer() << tr("Integrated addresses can only be created for account 0");
|
||||
return true;
|
||||
}
|
||||
payment_id = crypto::rand<crypto::hash8>();
|
||||
success_msg_writer() << tr("Random payment ID: ") << payment_id;
|
||||
success_msg_writer() << tr("Matching integrated address: ") << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype());
|
||||
return true;
|
||||
}
|
||||
if(tools::wallet2::parse_short_payment_id(args.back(), payment_id))
|
||||
{
|
||||
if (m_current_subaddress_account != 0)
|
||||
{
|
||||
fail_msg_writer() << tr("Integrated addresses can only be created for account 0");
|
||||
return true;
|
||||
}
|
||||
success_msg_writer() << m_wallet->get_account().get_public_integrated_address_str(payment_id, m_wallet->nettype());
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
address_parse_info info;
|
||||
if(get_account_address_from_str(info, m_wallet->nettype(), args.back()))
|
||||
{
|
||||
if (info.has_payment_id)
|
||||
{
|
||||
success_msg_writer() << boost::format(tr("Integrated address: %s, payment ID: %s")) %
|
||||
get_account_address_as_str(m_wallet->nettype(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
success_msg_writer() << (info.is_subaddress ? tr("Subaddress: ") : tr("Standard address: ")) << get_account_address_as_str(m_wallet->nettype(), info.is_subaddress, info.address);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
fail_msg_writer() << tr("failed to parse payment ID or address");
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
||||
bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
|
||||
{
|
||||
if (args.size() == 0)
|
||||
@@ -6732,7 +6727,7 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
|
||||
}
|
||||
else if (args.size() == 1 || (args[0] != "add" && args[0] != "delete"))
|
||||
{
|
||||
fail_msg_writer() << tr("usage: address_book [(add (<address> [pid <long or short payment id>])|<integrated address> [<description possibly with whitespaces>])|(delete <index>)]");
|
||||
fail_msg_writer() << tr("usage: address_book [(add (<address> [pid <long or short payment id>]) [<description possibly with whitespaces>])|(delete <index>)]");
|
||||
return true;
|
||||
}
|
||||
else if (args[0] == "add")
|
||||
|
||||
@@ -91,13 +91,13 @@ namespace cryptonote
|
||||
//! \return Prompts user for password and verifies against local file. Logs on error and returns `none`
|
||||
boost::optional<tools::password_container> get_and_verify_password() const;
|
||||
|
||||
bool new_wallet(const boost::program_options::variables_map& vm, const crypto::secret_key& recovery_key,
|
||||
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const crypto::secret_key& recovery_key,
|
||||
bool recover, bool two_random, const std::string &old_language);
|
||||
bool new_wallet(const boost::program_options::variables_map& vm, const cryptonote::account_public_address& address,
|
||||
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const cryptonote::account_public_address& address,
|
||||
const boost::optional<crypto::secret_key>& spendkey, const crypto::secret_key& viewkey);
|
||||
bool new_wallet(const boost::program_options::variables_map& vm,
|
||||
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm,
|
||||
const std::string &multisig_keys, const std::string &old_language);
|
||||
bool new_wallet(const boost::program_options::variables_map& vm, const std::string& device_name);
|
||||
boost::optional<epee::wipeable_string> new_wallet(const boost::program_options::variables_map& vm, const std::string& device_name);
|
||||
bool open_wallet(const boost::program_options::variables_map& vm);
|
||||
bool close_wallet();
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace cryptonote
|
||||
bool set_store_tx_info(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_auto_refresh(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_refresh_type(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_confirm_missing_payment_id(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_confirm_subaddress(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_ask_password(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_unit(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool set_min_output_count(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
@@ -167,7 +167,6 @@ namespace cryptonote
|
||||
void print_accounts();
|
||||
void print_accounts(const std::string& tag);
|
||||
bool print_address(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool print_integrated_address(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool address_book(const std::vector<std::string> &args = std::vector<std::string>());
|
||||
bool save(const std::vector<std::string> &args);
|
||||
bool save_watch_only(const std::vector<std::string> &args);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
|
||||
#define DEF_MONERO_VERSION "0.3.0.0-master"
|
||||
#define DEF_MONERO_VERSION "0.3.1.0"
|
||||
#define DEF_MONERO_RELEASE_NAME "Cool Cage"
|
||||
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
|
||||
|
||||
|
||||
@@ -744,14 +744,6 @@ std::string WalletImpl::address(uint32_t accountIndex, uint32_t addressIndex) co
|
||||
return m_wallet->get_subaddress_as_str({accountIndex, addressIndex});
|
||||
}
|
||||
|
||||
std::string WalletImpl::integratedAddress(const std::string &payment_id) const
|
||||
{
|
||||
crypto::hash8 pid;
|
||||
if (!tools::wallet2::parse_short_payment_id(payment_id, pid)) {
|
||||
return "";
|
||||
}
|
||||
return m_wallet->get_integrated_address_as_str(pid);
|
||||
}
|
||||
|
||||
std::string WalletImpl::secretViewKey() const
|
||||
{
|
||||
|
||||
@@ -88,7 +88,6 @@ public:
|
||||
std::string errorString() const;
|
||||
bool setPassword(const std::string &password);
|
||||
std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const;
|
||||
std::string integratedAddress(const std::string &payment_id) const;
|
||||
std::string secretViewKey() const;
|
||||
std::string publicViewKey() const;
|
||||
std::string secretSpendKey() const;
|
||||
|
||||
@@ -373,16 +373,6 @@ struct Wallet
|
||||
virtual void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const = 0;
|
||||
//! check if hard fork rules should be used
|
||||
virtual bool useForkRules(uint8_t version, int64_t early_blocks) const = 0;
|
||||
/*!
|
||||
* \brief integratedAddress - returns integrated address for current wallet address and given payment_id.
|
||||
* if passed "payment_id" param is an empty string or not-valid payment id string
|
||||
* (16 characters hexadecimal string) - random payment_id will be generated
|
||||
*
|
||||
* \param payment_id - 16 characters hexadecimal string or empty string if new random payment id needs to be
|
||||
* generated
|
||||
* \return - 106 characters string representing integrated address
|
||||
*/
|
||||
virtual std::string integratedAddress(const std::string &payment_id) const = 0;
|
||||
|
||||
/*!
|
||||
* \brief secretViewKey - returns secret view key
|
||||
|
||||
@@ -146,7 +146,7 @@ boost::optional<std::string> NodeRPCProxy::get_earliest_height(uint8_t version,
|
||||
CHECK_AND_ASSERT_MES(r, std::string(), "Failed to connect to daemon");
|
||||
CHECK_AND_ASSERT_MES(resp_t.status != CORE_RPC_STATUS_BUSY, resp_t.status, "Failed to connect to daemon");
|
||||
CHECK_AND_ASSERT_MES(resp_t.status == CORE_RPC_STATUS_OK, resp_t.status, "Failed to get hard fork status");
|
||||
m_earliest_height[version] = resp_t.enabled ? resp_t.earliest_height : std::numeric_limits<uint64_t>::max();
|
||||
m_earliest_height[version] = resp_t.earliest_height;
|
||||
}
|
||||
|
||||
earliest_height = m_earliest_height[version];
|
||||
|
||||
@@ -651,7 +651,7 @@ wallet2::wallet2(network_type nettype, bool restricted):
|
||||
m_auto_refresh(true),
|
||||
m_refresh_from_block_height(0),
|
||||
m_explicit_refresh_from_block_height(true),
|
||||
m_confirm_missing_payment_id(true),
|
||||
m_confirm_subaddress(true),
|
||||
m_confirm_non_default_ring_size(true),
|
||||
m_ask_password(true),
|
||||
m_min_output_count(0),
|
||||
@@ -887,6 +887,14 @@ cryptonote::account_public_address wallet2::get_subaddress(const cryptonote::sub
|
||||
return hwdev.get_subaddress(m_account.get_keys(), index);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
boost::optional<cryptonote::subaddress_index> wallet2::get_subaddress_index(const cryptonote::account_public_address& address) const
|
||||
{
|
||||
auto index = m_subaddresses.find(address.m_spend_public_key);
|
||||
if (index == m_subaddresses.end())
|
||||
return boost::none;
|
||||
return index->second;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
crypto::public_key wallet2::get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const
|
||||
{
|
||||
hw::device &hwdev = m_account.get_device();
|
||||
@@ -898,6 +906,7 @@ std::string wallet2::get_subaddress_as_str(const cryptonote::subaddress_index& i
|
||||
cryptonote::account_public_address address = get_subaddress(index);
|
||||
return cryptonote::get_account_address_as_str(m_nettype, !index.is_zero(), address);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string wallet2::get_integrated_address_as_str(const crypto::hash8& payment_id) const
|
||||
{
|
||||
@@ -1105,7 +1114,6 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
// (that is, the prunable stuff may or may not be included)
|
||||
if (!miner_tx && !pool)
|
||||
process_unconfirmed(txid, tx, height);
|
||||
std::vector<size_t> outs;
|
||||
std::unordered_map<cryptonote::subaddress_index, uint64_t> tx_money_got_in_outs; // per receiving subaddress index
|
||||
crypto::public_key tx_pub_key = null_pkey;
|
||||
|
||||
@@ -1123,6 +1131,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
|
||||
uint64_t total_received_1 = 0;
|
||||
while (!tx.vout.empty())
|
||||
{
|
||||
std::vector<size_t> outs;
|
||||
// if tx.vout is not empty, we loop through all tx pubkeys
|
||||
|
||||
tx_extra_pub_key pub_key_field;
|
||||
@@ -2623,8 +2632,8 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
|
||||
value2.SetUint64(m_refresh_from_block_height);
|
||||
json.AddMember("refresh_height", value2, json.GetAllocator());
|
||||
|
||||
value2.SetInt(m_confirm_missing_payment_id ? 1 :0);
|
||||
json.AddMember("confirm_missing_payment_id", value2, json.GetAllocator());
|
||||
value2.SetInt(m_confirm_subaddress ? 1 :0);
|
||||
json.AddMember("confirm_subaddress", value2, json.GetAllocator());
|
||||
|
||||
value2.SetInt(m_confirm_non_default_ring_size ? 1 :0);
|
||||
json.AddMember("confirm_non_default_ring_size", value2, json.GetAllocator());
|
||||
@@ -2734,7 +2743,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
|
||||
m_default_priority = 0;
|
||||
m_auto_refresh = true;
|
||||
m_refresh_type = RefreshType::RefreshDefault;
|
||||
m_confirm_missing_payment_id = true;
|
||||
m_confirm_subaddress = true;
|
||||
m_confirm_non_default_ring_size = true;
|
||||
m_ask_password = true;
|
||||
m_min_output_count = 0;
|
||||
@@ -2837,8 +2846,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
|
||||
}
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, refresh_height, uint64_t, Uint64, false, 0);
|
||||
m_refresh_from_block_height = field_refresh_height;
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_missing_payment_id, int, Int, false, true);
|
||||
m_confirm_missing_payment_id = field_confirm_missing_payment_id;
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_subaddress, int, Int, false, true);
|
||||
m_confirm_subaddress = field_confirm_subaddress;
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_non_default_ring_size, int, Int, false, true);
|
||||
m_confirm_non_default_ring_size = field_confirm_non_default_ring_size;
|
||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, ask_password, int, Int, false, true);
|
||||
@@ -5914,6 +5923,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
bool is_shortly_after_segregation_fork = height >= segregation_fork_height && height < segregation_fork_height + SEGREGATION_FORK_VICINITY;
|
||||
bool is_after_segregation_fork = height >= segregation_fork_height;
|
||||
|
||||
|
||||
// get histogram for the amounts we need
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request req_t = AUTO_VAL_INIT(req_t);
|
||||
cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response resp_t = AUTO_VAL_INIT(resp_t);
|
||||
@@ -5985,6 +5995,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
|
||||
COMMAND_RPC_GET_OUTPUTS_BIN::request req = AUTO_VAL_INIT(req);
|
||||
COMMAND_RPC_GET_OUTPUTS_BIN::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
|
||||
|
||||
|
||||
size_t num_selected_transfers = 0;
|
||||
for(size_t idx: selected_transfers)
|
||||
{
|
||||
@@ -8124,7 +8135,7 @@ bool wallet2::use_fork_rules(uint8_t version, int64_t early_blocks) const
|
||||
result = m_node_rpc_proxy.get_earliest_height(version, earliest_height);
|
||||
throw_on_rpc_response_error(result, "get_hard_fork_info");
|
||||
|
||||
bool close_enough = height >= earliest_height - early_blocks && earliest_height != std::numeric_limits<uint64_t>::max(); // start using the rules that many blocks beforehand
|
||||
bool close_enough = height >= earliest_height - early_blocks; // start using the rules that many blocks beforehand
|
||||
if (close_enough)
|
||||
LOG_PRINT_L2("Using v" << (unsigned)version << " rules");
|
||||
else
|
||||
@@ -8907,6 +8918,7 @@ std::string wallet2::get_reserve_proof(const boost::optional<std::pair<uint32_t,
|
||||
|
||||
if (account_minreserve)
|
||||
{
|
||||
THROW_WALLET_EXCEPTION_IF(account_minreserve->second == 0, error::wallet_internal_error, "Proved amount must be greater than 0");
|
||||
// minimize the number of outputs included in the proof, by only picking the N largest outputs that can cover the requested min reserve amount
|
||||
std::sort(selected_transfers.begin(), selected_transfers.end(), [&](const size_t a, const size_t b)
|
||||
{ return m_transfers[a].amount() > m_transfers[b].amount(); });
|
||||
@@ -9572,6 +9584,17 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
||||
std::unordered_set<crypto::hash> spent_txids; // For each spent key image, search for a tx in m_transfers that uses it as input.
|
||||
std::vector<size_t> swept_transfers; // If such a spending tx wasn't found in m_transfers, this means the spending tx
|
||||
// was created by sweep_all, so we can't know the spent height and other detailed info.
|
||||
std::unordered_map<crypto::key_image, crypto::hash> spent_key_images;
|
||||
|
||||
for (const transfer_details &td: m_transfers)
|
||||
{
|
||||
for (const cryptonote::txin_v& in : td.m_tx.vin)
|
||||
{
|
||||
if (in.type() == typeid(cryptonote::txin_to_key))
|
||||
spent_key_images.insert(std::make_pair(boost::get<cryptonote::txin_to_key>(in).k_image, td.m_txid));
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < signed_key_images.size(); ++i)
|
||||
{
|
||||
transfer_details &td = m_transfers[i];
|
||||
@@ -9585,28 +9608,11 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
||||
|
||||
if (i < daemon_resp.spent_status.size() && daemon_resp.spent_status[i] == COMMAND_RPC_IS_KEY_IMAGE_SPENT::SPENT_IN_BLOCKCHAIN)
|
||||
{
|
||||
bool is_spent_tx_found = false;
|
||||
for (auto it = m_transfers.rbegin(); &(*it) != &td; ++it)
|
||||
{
|
||||
bool is_spent_tx = false;
|
||||
for(const cryptonote::txin_v& in : it->m_tx.vin)
|
||||
{
|
||||
if(in.type() == typeid(cryptonote::txin_to_key) && td.m_key_image == boost::get<cryptonote::txin_to_key>(in).k_image)
|
||||
{
|
||||
is_spent_tx = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (is_spent_tx)
|
||||
{
|
||||
is_spent_tx_found = true;
|
||||
spent_txids.insert(it->m_txid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_spent_tx_found)
|
||||
const std::unordered_map<crypto::key_image, crypto::hash>::const_iterator skii = spent_key_images.find(td.m_key_image);
|
||||
if (skii == spent_key_images.end())
|
||||
swept_transfers.push_back(i);
|
||||
else
|
||||
spent_txids.insert(skii->second);
|
||||
}
|
||||
}
|
||||
MDEBUG("Total: " << print_money(spent) << " spent, " << print_money(unspent) << " unspent");
|
||||
@@ -9729,11 +9735,10 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
|
||||
{
|
||||
const transfer_details& td = m_transfers[n];
|
||||
confirmed_transfer_details pd;
|
||||
pd.m_change = (uint64_t)-1; // cahnge is unknown
|
||||
pd.m_change = (uint64_t)-1; // change is unknown
|
||||
pd.m_amount_in = pd.m_amount_out = td.amount(); // fee is unknown
|
||||
std::string err;
|
||||
pd.m_block_height = get_daemon_blockchain_height(err); // spent block height is unknown, so hypothetically set to the highest
|
||||
crypto::hash spent_txid = crypto::rand<crypto::hash>(); // spent txid is unknown, so hypothetically set to random
|
||||
pd.m_block_height = 0; // spent block height is unknown
|
||||
const crypto::hash &spent_txid = crypto::null_hash; // spent txid is unknown
|
||||
m_confirmed_txs.insert(std::make_pair(spent_txid, pd));
|
||||
}
|
||||
}
|
||||
@@ -9828,18 +9833,20 @@ size_t wallet2::import_outputs(const std::vector<tools::wallet2::transfer_detail
|
||||
crypto::public_key tx_pub_key = get_tx_pub_key_from_received_outs(td);
|
||||
const std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(td.m_tx);
|
||||
|
||||
THROW_WALLET_EXCEPTION_IF(td.m_tx.vout[td.m_internal_output_index].target.type() != typeid(cryptonote::txout_to_key),
|
||||
error::wallet_internal_error, "Unsupported output type");
|
||||
const crypto::public_key& out_key = boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key;
|
||||
bool r = cryptonote::generate_key_image_helper(m_account.get_keys(), m_subaddresses, out_key, tx_pub_key, additional_tx_pub_keys, td.m_internal_output_index, in_ephemeral, td.m_key_image, m_account.get_device());
|
||||
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Failed to generate key image");
|
||||
expand_subaddresses(td.m_subaddr_index);
|
||||
td.m_key_image_known = true;
|
||||
td.m_key_image_partial = false;
|
||||
THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != boost::get<cryptonote::txout_to_key>(td.m_tx.vout[td.m_internal_output_index].target).key,
|
||||
THROW_WALLET_EXCEPTION_IF(in_ephemeral.pub != out_key,
|
||||
error::wallet_internal_error, "key_image generated ephemeral public key not matched with output_key at index " + boost::lexical_cast<std::string>(i));
|
||||
|
||||
m_key_images[td.m_key_image] = m_transfers.size();
|
||||
m_pub_keys[td.get_public_key()] = m_transfers.size();
|
||||
m_transfers.push_back(td);
|
||||
m_transfers.push_back(std::move(td));
|
||||
}
|
||||
|
||||
return m_transfers.size();
|
||||
|
||||
@@ -624,6 +624,7 @@ namespace tools
|
||||
// Subaddress scheme
|
||||
cryptonote::account_public_address get_subaddress(const cryptonote::subaddress_index& index) const;
|
||||
cryptonote::account_public_address get_address() const { return get_subaddress({0,0}); }
|
||||
boost::optional<cryptonote::subaddress_index> get_subaddress_index(const cryptonote::account_public_address& address) const;
|
||||
crypto::public_key get_subaddress_spend_public_key(const cryptonote::subaddress_index& index) const;
|
||||
std::vector<crypto::public_key> get_subaddress_spend_public_keys(uint32_t account, uint32_t begin, uint32_t end) const;
|
||||
std::string get_subaddress_as_str(const cryptonote::subaddress_index& index) const;
|
||||
@@ -851,8 +852,8 @@ namespace tools
|
||||
void set_default_priority(uint32_t p) { m_default_priority = p; }
|
||||
bool auto_refresh() const { return m_auto_refresh; }
|
||||
void auto_refresh(bool r) { m_auto_refresh = r; }
|
||||
bool confirm_missing_payment_id() const { return m_confirm_missing_payment_id; }
|
||||
void confirm_missing_payment_id(bool always) { m_confirm_missing_payment_id = always; }
|
||||
bool confirm_subaddress() const { return m_confirm_subaddress; }
|
||||
void confirm_subaddress(bool always) { m_confirm_subaddress = always; }
|
||||
bool ask_password() const { return m_ask_password; }
|
||||
void ask_password(bool always) { m_ask_password = always; }
|
||||
void set_min_output_count(uint32_t count) { m_min_output_count = count; }
|
||||
@@ -1196,7 +1197,7 @@ namespace tools
|
||||
// If m_refresh_from_block_height is explicitly set to zero we need this to differentiate it from the case that
|
||||
// m_refresh_from_block_height was defaulted to zero.*/
|
||||
bool m_explicit_refresh_from_block_height;
|
||||
bool m_confirm_missing_payment_id;
|
||||
bool m_confirm_subaddress;
|
||||
bool m_confirm_non_default_ring_size;
|
||||
bool m_ask_password;
|
||||
uint32_t m_min_output_count;
|
||||
|
||||
@@ -336,14 +336,20 @@ namespace tools
|
||||
std::map<uint32_t, uint64_t> unlocked_balance_per_subaddress = m_wallet->unlocked_balance_per_subaddress(req.account_index);
|
||||
std::vector<tools::wallet2::transfer_details> transfers;
|
||||
m_wallet->get_transfers(transfers);
|
||||
for (const auto& i : balance_per_subaddress)
|
||||
std::set<uint32_t> address_indices = req.address_indices;
|
||||
if (address_indices.empty())
|
||||
{
|
||||
for (const auto& i : balance_per_subaddress)
|
||||
address_indices.insert(i.first);
|
||||
}
|
||||
for (uint32_t i : address_indices)
|
||||
{
|
||||
wallet_rpc::COMMAND_RPC_GET_BALANCE::per_subaddress_info info;
|
||||
info.address_index = i.first;
|
||||
info.address_index = i;
|
||||
cryptonote::subaddress_index index = {req.account_index, info.address_index};
|
||||
info.address = m_wallet->get_subaddress_as_str(index);
|
||||
info.balance = i.second;
|
||||
info.unlocked_balance = unlocked_balance_per_subaddress[i.first];
|
||||
info.balance = balance_per_subaddress[i];
|
||||
info.unlocked_balance = unlocked_balance_per_subaddress[i];
|
||||
info.label = m_wallet->get_subaddress_label(index);
|
||||
info.num_unspent_outputs = std::count_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == index; });
|
||||
res.per_subaddress.push_back(info);
|
||||
@@ -397,6 +403,27 @@ namespace tools
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_getaddress_index(const wallet_rpc::COMMAND_RPC_GET_ADDRESS_INDEX::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS_INDEX::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
cryptonote::address_parse_info info;
|
||||
if(!get_account_address_from_str(info, m_wallet->nettype(), req.address))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "Invalid address";
|
||||
return false;
|
||||
}
|
||||
auto index = m_wallet->get_subaddress_index(info.address);
|
||||
if (!index)
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
|
||||
er.message = "Address doesn't belong to the wallet";
|
||||
return false;
|
||||
}
|
||||
res.index = *index;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
bool wallet_rpc_server::on_create_address(const wallet_rpc::COMMAND_RPC_CREATE_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_CREATE_ADDRESS::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
@@ -1938,8 +1965,8 @@ namespace tools
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) {
|
||||
if (i->second.m_tx_hash == txid)
|
||||
{
|
||||
fill_transfer_entry(res.transfer, i->second.m_tx_hash, i->first, i->second);
|
||||
return true;
|
||||
res.transfers.resize(res.transfers.size() + 1);
|
||||
fill_transfer_entry(res.transfers.back(), i->second.m_tx_hash, i->first, i->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1948,8 +1975,8 @@ namespace tools
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::confirmed_transfer_details>>::const_iterator i = payments_out.begin(); i != payments_out.end(); ++i) {
|
||||
if (i->first == txid)
|
||||
{
|
||||
fill_transfer_entry(res.transfer, i->first, i->second);
|
||||
return true;
|
||||
res.transfers.resize(res.transfers.size() + 1);
|
||||
fill_transfer_entry(res.transfers.back(), i->first, i->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1958,8 +1985,8 @@ namespace tools
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::unconfirmed_transfer_details>>::const_iterator i = upayments.begin(); i != upayments.end(); ++i) {
|
||||
if (i->first == txid)
|
||||
{
|
||||
fill_transfer_entry(res.transfer, i->first, i->second);
|
||||
return true;
|
||||
res.transfers.resize(res.transfers.size() + 1);
|
||||
fill_transfer_entry(res.transfers.back(), i->first, i->second);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1970,11 +1997,17 @@ namespace tools
|
||||
for (std::list<std::pair<crypto::hash, tools::wallet2::pool_payment_details>>::const_iterator i = pool_payments.begin(); i != pool_payments.end(); ++i) {
|
||||
if (i->second.m_pd.m_tx_hash == txid)
|
||||
{
|
||||
fill_transfer_entry(res.transfer, i->first, i->second);
|
||||
return true;
|
||||
res.transfers.resize(res.transfers.size() + 1);
|
||||
fill_transfer_entry(res.transfers.back(), i->first, i->second);
|
||||
}
|
||||
}
|
||||
|
||||
if (!res.transfers.empty())
|
||||
{
|
||||
res.transfer = res.transfers.front(); // backward compat
|
||||
return true;
|
||||
}
|
||||
|
||||
er.code = WALLET_RPC_ERROR_CODE_WRONG_TXID;
|
||||
er.message = "Transaction not found.";
|
||||
return false;
|
||||
@@ -3007,6 +3040,7 @@ just_dir:
|
||||
wrpc.send_stop_signal();
|
||||
});
|
||||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Starting wallet RPC server"));
|
||||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("WARNING: Payment IDs/integrated addresses will be deprecated soon. Use sub-addresses."));
|
||||
try
|
||||
{
|
||||
wrpc.run();
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace tools
|
||||
BEGIN_JSON_RPC_MAP("/json_rpc")
|
||||
MAP_JON_RPC_WE("get_balance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE)
|
||||
MAP_JON_RPC_WE("get_address", on_getaddress, wallet_rpc::COMMAND_RPC_GET_ADDRESS)
|
||||
MAP_JON_RPC_WE("get_address_index", on_getaddress_index, wallet_rpc::COMMAND_RPC_GET_ADDRESS_INDEX)
|
||||
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE)
|
||||
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_rpc::COMMAND_RPC_GET_ADDRESS)
|
||||
MAP_JON_RPC_WE("create_address", on_create_address, wallet_rpc::COMMAND_RPC_CREATE_ADDRESS)
|
||||
@@ -141,6 +142,7 @@ namespace tools
|
||||
//json_rpc
|
||||
bool on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er);
|
||||
bool on_getaddress(const wallet_rpc::COMMAND_RPC_GET_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er);
|
||||
bool on_getaddress_index(const wallet_rpc::COMMAND_RPC_GET_ADDRESS_INDEX::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS_INDEX::response& res, epee::json_rpc::error& er);
|
||||
bool on_create_address(const wallet_rpc::COMMAND_RPC_CREATE_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_CREATE_ADDRESS::response& res, epee::json_rpc::error& er);
|
||||
bool on_label_address(const wallet_rpc::COMMAND_RPC_LABEL_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_LABEL_ADDRESS::response& res, epee::json_rpc::error& er);
|
||||
bool on_get_accounts(const wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNTS::response& res, epee::json_rpc::error& er);
|
||||
|
||||
@@ -39,6 +39,17 @@
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.rpc"
|
||||
|
||||
// When making *any* change here, bump minor
|
||||
// If the change is incompatible, then bump major and set minor to 0
|
||||
// This ensures WALLET_RPC_VERSION always increases, that every change
|
||||
// has its own version, and that clients can just test major to see
|
||||
// whether they can talk to a given wallet without having to know in
|
||||
// advance which version they will stop working with
|
||||
// Don't go over 32767 for any of these
|
||||
#define WALLET_RPC_VERSION_MAJOR 1
|
||||
#define WALLET_RPC_VERSION_MINOR 4
|
||||
#define MAKE_WALLET_RPC_VERSION(major,minor) (((major)<<16)|(minor))
|
||||
#define WALLET_RPC_VERSION MAKE_WALLET_RPC_VERSION(WALLET_RPC_VERSION_MAJOR, WALLET_RPC_VERSION_MINOR)
|
||||
namespace tools
|
||||
{
|
||||
namespace wallet_rpc
|
||||
@@ -51,8 +62,10 @@ namespace wallet_rpc
|
||||
struct request
|
||||
{
|
||||
uint32_t account_index;
|
||||
std::set<uint32_t> address_indices;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(account_index)
|
||||
KV_SERIALIZE(address_indices)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
@@ -130,6 +143,25 @@ namespace wallet_rpc
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_GET_ADDRESS_INDEX
|
||||
{
|
||||
struct request
|
||||
{
|
||||
std::string address;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(address)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
cryptonote::subaddress_index index;
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(index)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_CREATE_ADDRESS
|
||||
{
|
||||
struct request
|
||||
@@ -1311,9 +1343,11 @@ namespace wallet_rpc
|
||||
struct response
|
||||
{
|
||||
transfer_entry transfer;
|
||||
std::list<transfer_entry> transfers;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(transfer);
|
||||
KV_SERIALIZE(transfers);
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user