aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/epee/include/net/http_client.h23
-rw-r--r--src/blockchain_utilities/blockchain_export.cpp15
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp31
-rw-r--r--src/blocks/CMakeLists.txt4
-rw-r--r--src/common/download.cpp182
-rw-r--r--src/common/download.h10
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp4
-rw-r--r--src/cryptonote_config.h1
-rw-r--r--src/cryptonote_core/blockchain.cpp22
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp69
-rw-r--r--src/cryptonote_core/cryptonote_core.h5
-rw-r--r--src/cryptonote_core/tx_pool.cpp10
-rw-r--r--src/daemon/CMakeLists.txt4
-rw-r--r--src/rpc/core_rpc_server.cpp4
-rw-r--r--src/simplewallet/simplewallet.cpp7
-rw-r--r--src/wallet/wallet2.cpp6
-rw-r--r--src/wallet/wallet2.h18
-rw-r--r--tests/unit_tests/fee.cpp57
18 files changed, 367 insertions, 105 deletions
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index d73eda39c..67e63f7bf 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -337,6 +337,11 @@ using namespace std;
return true;
}
//---------------------------------------------------------------------------
+ virtual bool on_header(const http_response_info &headers)
+ {
+ return true;
+ }
+ //---------------------------------------------------------------------------
inline
bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
@@ -505,6 +510,12 @@ using namespace std;
m_header_cache.erase(m_header_cache.begin()+pos+4, m_header_cache.end());
analize_cached_header_and_invoke_state();
+ if (!on_header(m_response_info))
+ {
+ MDEBUG("Connection cancelled by on_header");
+ m_state = reciev_machine_state_done;
+ return false;
+ }
m_header_cache.clear();
if(!recv_buff.size() && (m_state != reciev_machine_state_error && m_state != reciev_machine_state_done))
need_more_data = true;
@@ -527,7 +538,11 @@ using namespace std;
}
CHECK_AND_ASSERT_MES(m_len_in_remain >= recv_buff.size(), false, "m_len_in_remain >= recv_buff.size()");
m_len_in_remain -= recv_buff.size();
- m_pcontent_encoding_handler->update_in(recv_buff);
+ if (!m_pcontent_encoding_handler->update_in(recv_buff))
+ {
+ m_state = reciev_machine_state_done;
+ return false;
+ }
if(m_len_in_remain == 0)
m_state = reciev_machine_state_done;
@@ -700,7 +715,11 @@ using namespace std;
m_len_in_remain = 0;
}
- m_pcontent_encoding_handler->update_in(chunk_body);
+ if (!m_pcontent_encoding_handler->update_in(chunk_body))
+ {
+ m_state = reciev_machine_state_error;
+ return false;
+ }
if(!m_len_in_remain)
m_chunked_state = http_chunked_state_chunk_head;
diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp
index 269710ee1..f145bc107 100644
--- a/src/blockchain_utilities/blockchain_export.cpp
+++ b/src/blockchain_utilities/blockchain_export.cpp
@@ -57,6 +57,8 @@ std::string join_set_strings(const std::unordered_set<std::string>& db_types_all
int main(int argc, char* argv[])
{
+ TRY_ENTRY();
+
epee::string_tools::set_module_name_and_folder(argv[0]);
std::string default_db_type = "lmdb";
@@ -80,7 +82,7 @@ int main(int argc, char* argv[])
po::options_description desc_cmd_only("Command line options");
po::options_description desc_cmd_sett("Command line options and settings options");
const command_line::arg_descriptor<std::string> arg_output_file = {"output-file", "Specify output file", "", true};
- const command_line::arg_descriptor<uint32_t> arg_log_level = {"log-level", "", log_level};
+ const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
const command_line::arg_descriptor<uint64_t> arg_block_stop = {"block-stop", "Stop at block number", block_stop};
const command_line::arg_descriptor<bool> arg_testnet_on = {
"testnet"
@@ -124,11 +126,13 @@ int main(int argc, char* argv[])
return 1;
}
- log_level = command_line::get_arg(vm, arg_log_level);
+ mlog_configure(mlog_get_default_log_path("monero-blockchain-export.log"), true);
+ if (!vm["log-level"].defaulted())
+ mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
+ else
+ mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
block_stop = command_line::get_arg(vm, arg_block_stop);
- mlog_configure(mlog_get_default_log_path("monero-blockchain-export.log"), true);
- mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
bool opt_testnet = command_line::get_arg(vm, arg_testnet_on);
@@ -226,4 +230,7 @@ int main(int argc, char* argv[])
}
CHECK_AND_ASSERT_MES(r, false, "Failed to export blockchain raw data");
LOG_PRINT_L0("Blockchain raw data exported OK");
+ return 0;
+
+ CATCH_ENTRY("Export error", 1);
}
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index c91cdb430..b2c217ca1 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -596,6 +596,8 @@ int import_from_file(FakeCore& simple_core, const std::string& import_file_path,
int main(int argc, char* argv[])
{
+ TRY_ENTRY();
+
epee::string_tools::set_module_name_and_folder(argv[0]);
std::string default_db_type = "lmdb";
@@ -622,7 +624,7 @@ int main(int argc, char* argv[])
po::options_description desc_cmd_only("Command line options");
po::options_description desc_cmd_sett("Command line options and settings options");
const command_line::arg_descriptor<std::string> arg_input_file = {"input-file", "Specify input file", "", true};
- const command_line::arg_descriptor<uint32_t> arg_log_level = {"log-level", "", log_level};
+ const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
const command_line::arg_descriptor<uint64_t> arg_block_stop = {"block-stop", "Stop at block number", block_stop};
const command_line::arg_descriptor<uint64_t> arg_batch_size = {"batch-size", "", db_batch_size};
const command_line::arg_descriptor<uint64_t> arg_pop_blocks = {"pop-blocks", "Remove blocks from end of blockchain", num_blocks};
@@ -682,7 +684,6 @@ int main(int argc, char* argv[])
if (! r)
return 1;
- log_level = command_line::get_arg(vm, arg_log_level);
opt_verify = command_line::get_arg(vm, arg_verify);
opt_batch = command_line::get_arg(vm, arg_batch);
opt_resume = command_line::get_arg(vm, arg_resume);
@@ -725,7 +726,11 @@ int main(int argc, char* argv[])
db_arg_str = command_line::get_arg(vm, arg_database);
mlog_configure(mlog_get_default_log_path("monero-blockchain-import.log"), true);
- mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
+ if (!vm["log-level"].defaulted())
+ mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
+ else
+ mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
+
MINFO("Starting...");
boost::filesystem::path fs_import_file_path;
@@ -762,7 +767,11 @@ int main(int argc, char* argv[])
return 1;
}
- if ((db_type == "lmdb") || (db_type == "berkeley"))
+ if ((db_type == "lmdb")
+#if defined(BERKELEY_DB)
+ || (db_type == "berkeley")
+#endif
+ )
{
db_engine_compiled = "blockchain_db";
}
@@ -799,13 +808,11 @@ int main(int argc, char* argv[])
// properties to do so. Both ways work, but fake core isn't necessary in that
// circumstance.
- // for multi_db_runtime:
- if (db_type == "lmdb" || db_type == "berkeley")
- {
- fake_core_db simple_core(m_config_folder, opt_testnet, opt_batch, db_type, db_flags);
- import_from_file(simple_core, import_file_path, block_stop);
- }
- else
+ if (db_type != "lmdb"
+#if defined(BERKELEY_DB)
+ && db_type != "berkeley"
+#endif
+ )
{
std::cerr << "database type unrecognized" << ENDL;
return 1;
@@ -850,4 +857,6 @@ int main(int argc, char* argv[])
// calls delete on its BlockchainDB derived class' object, which closes its
// files.
return 0;
+
+ CATCH_ENTRY("Import error", 1);
}
diff --git a/src/blocks/CMakeLists.txt b/src/blocks/CMakeLists.txt
index 2a5c781e0..3a866af5b 100644
--- a/src/blocks/CMakeLists.txt
+++ b/src/blocks/CMakeLists.txt
@@ -30,8 +30,8 @@ if(APPLE)
add_library(blocks STATIC blockexports.c)
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
else()
- add_custom_command(OUTPUT blocks.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
- add_custom_command(OUTPUT testnet_blocks.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
+ add_custom_command(OUTPUT blocks.o MAIN_DEPENDENCY blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocks.o blocks.dat)
+ add_custom_command(OUTPUT testnet_blocks.o MAIN_DEPENDENCY testnet_blocks.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/testnet_blocks.o testnet_blocks.dat)
add_library(blocks STATIC blocks.o testnet_blocks.o blockexports.c)
set_target_properties(blocks PROPERTIES LINKER_LANGUAGE C)
endif()
diff --git a/src/common/download.cpp b/src/common/download.cpp
index c5ee797d0..28aac5a59 100644
--- a/src/common/download.cpp
+++ b/src/common/download.cpp
@@ -27,6 +27,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
+#include <atomic>
#include <boost/filesystem.hpp>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
@@ -40,27 +41,82 @@
namespace tools
{
- static bool download_thread(const std::string &path, const std::string &url)
+ struct download_thread_control
{
+ const std::string path;
+ const std::string uri;
+ std::function<void(const std::string&, const std::string&, bool)> result_cb;
+ std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress_cb;
+ bool stop;
+ bool stopped;
+ bool success;
+ boost::thread thread;
+ boost::mutex mutex;
+
+ download_thread_control(const std::string &path, const std::string &uri, std::function<void(const std::string&, const std::string&, bool)> result_cb, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress_cb):
+ path(path), uri(uri), result_cb(result_cb), progress_cb(progress_cb), stop(false), stopped(false), success(false) {}
+ ~download_thread_control() { if (thread.joinable()) thread.detach(); }
+ };
+
+ static void download_thread(download_async_handle control)
+ {
+ static std::atomic<unsigned int> thread_id(0);
+
+ MLOG_SET_THREAD_NAME("DL" + std::to_string(thread_id++));
+
+ struct stopped_setter
+ {
+ stopped_setter(const download_async_handle &control): control(control) {}
+ ~stopped_setter() { control->stopped = true; }
+ download_async_handle control;
+ } stopped_setter(control);
+
try
{
- MINFO("Downloading " << url << " to " << path);
+ boost::unique_lock<boost::mutex> lock(control->mutex);
+ MINFO("Downloading " << control->uri << " to " << control->path);
std::ofstream f;
- f.open(path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
+ f.open(control->path, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
if (!f.good()) {
- MERROR("Failed to open file " << path);
- return false;
+ MERROR("Failed to open file " << control->path);
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
class download_client: public epee::net_utils::http::http_simple_client
{
public:
- download_client(std::ofstream &f): f(f) {}
+ download_client(download_async_handle control, std::ofstream &f):
+ control(control), f(f), content_length(-1), total(0) {}
virtual ~download_client() { f.close(); }
+ virtual bool on_header(const epee::net_utils::http::http_response_info &headers)
+ {
+ ssize_t length;
+ if (epee::string_tools::get_xtype_from_string(length, headers.m_header_info.m_content_length) && length >= 0)
+ {
+ MINFO("Content-Length: " << length);
+ content_length = length;
+ boost::filesystem::path path(control->path);
+ boost::filesystem::space_info si = boost::filesystem::space(path);
+ if (si.available < (size_t)content_length)
+ {
+ const uint64_t avail = (si.available + 1023) / 1024, needed = (content_length + 1023) / 1024;
+ MERROR("Not enough space to download " << needed << " kB to " << path << " (" << avail << " kB available)");
+ return false;
+ }
+ }
+ return true;
+ }
virtual bool handle_target_data(std::string &piece_of_transfer)
{
try
{
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ if (control->stop)
+ return false;
f << piece_of_transfer;
+ total += piece_of_transfer.size();
+ if (control->progress_cb && !control->progress_cb(control->path, control->uri, total, content_length))
+ return false;
return f.good();
}
catch (const std::exception &e)
@@ -70,69 +126,145 @@ namespace tools
}
}
private:
+ download_async_handle control;
std::ofstream &f;
- } client(f);
+ ssize_t content_length;
+ size_t total;
+ } client(control, f);
epee::net_utils::http::url_content u_c;
- if (!epee::net_utils::parse_url(url, u_c))
+ if (!epee::net_utils::parse_url(control->uri, u_c))
{
- MWARNING("Failed to parse URL " << url);
- return false;
+ MERROR("Failed to parse URL " << control->uri);
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
if (u_c.host.empty())
{
- MWARNING("Failed to determine address from URL " << url);
- return false;
+ MERROR("Failed to determine address from URL " << control->uri);
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
+
+ lock.unlock();
+
uint16_t port = u_c.port ? u_c.port : 80;
MDEBUG("Connecting to " << u_c.host << ":" << port);
client.set_server(u_c.host, std::to_string(port), boost::none);
if (!client.connect(std::chrono::seconds(30)))
{
- MERROR("Failed to connect to " << url);
- return false;
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ MERROR("Failed to connect to " << control->uri);
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
MDEBUG("GETting " << u_c.uri);
const epee::net_utils::http::http_response_info *info = NULL;
if (!client.invoke_get(u_c.uri, std::chrono::seconds(30), "", &info))
{
- MERROR("Failed to connect to " << url);
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ MERROR("Failed to connect to " << control->uri);
client.disconnect();
- return false;
+ control->result_cb(control->path, control->uri, control->success);
+ return;
+ }
+ if (control->stop)
+ {
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ MDEBUG("Download cancelled");
+ client.disconnect();
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
if (!info)
{
- MERROR("Failed invoking GET command to " << url << ", no status info returned");
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ MERROR("Failed invoking GET command to " << control->uri << ", no status info returned");
client.disconnect();
- return false;
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
MDEBUG("response code: " << info->m_response_code);
+ MDEBUG("response length: " << info->m_header_info.m_content_length);
MDEBUG("response comment: " << info->m_response_comment);
MDEBUG("response body: " << info->m_body);
for (const auto &f: info->m_additional_fields)
MDEBUG("additional field: " << f.first << ": " << f.second);
if (info->m_response_code != 200)
{
+ boost::lock_guard<boost::mutex> lock(control->mutex);
MERROR("Status code " << info->m_response_code);
client.disconnect();
- return false;
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
client.disconnect();
f.close();
MDEBUG("Download complete");
- return true;
+ lock.lock();
+ control->success = true;
+ control->result_cb(control->path, control->uri, control->success);
+ return;
}
catch (const std::exception &e)
{
MERROR("Exception in download thread: " << e.what());
- return false;
+ // fall through and call result_cb not from the catch block to avoid another exception
}
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ control->result_cb(control->path, control->uri, control->success);
}
- bool download(const std::string &path, const std::string &url)
+ bool download(const std::string &path, const std::string &url, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> cb)
{
- bool success;
- std::unique_ptr<boost::thread> thread(new boost::thread([&](){ success = download_thread(path, url); }));
- thread->join();
+ bool success = false;
+ download_async_handle handle = download_async(path, url, [&success](const std::string&, const std::string&, bool result) {success = result;}, cb);
+ download_wait(handle);
return success;
}
+
+ download_async_handle download_async(const std::string &path, const std::string &url, std::function<void(const std::string&, const std::string&, bool)> result, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress)
+ {
+ download_async_handle control = std::make_shared<download_thread_control>(path, url, result, progress);
+ control->thread = boost::thread([control](){ download_thread(control); });
+ return control;
+ }
+
+ bool download_finished(const download_async_handle &control)
+ {
+ CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle");
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ return control->stopped;
+ }
+
+ bool download_error(const download_async_handle &control)
+ {
+ CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle");
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ return !control->success;
+ }
+
+ bool download_wait(const download_async_handle &control)
+ {
+ CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle");
+ {
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ if (control->stopped)
+ return true;
+ }
+ control->thread.join();
+ return true;
+ }
+
+ bool download_cancel(const download_async_handle &control)
+ {
+ CHECK_AND_ASSERT_MES(control != 0, false, "NULL async download handle");
+ {
+ boost::lock_guard<boost::mutex> lock(control->mutex);
+ if (control->stopped)
+ return true;
+ control->stop = true;
+ }
+ control->thread.join();
+ return true;
+ }
}
diff --git a/src/common/download.h b/src/common/download.h
index ab7644689..917cb2278 100644
--- a/src/common/download.h
+++ b/src/common/download.h
@@ -32,5 +32,13 @@
namespace tools
{
- bool download(const std::string &path, const std::string &url);
+ struct download_thread_control;
+ typedef std::shared_ptr<download_thread_control> download_async_handle;
+
+ bool download(const std::string &path, const std::string &url, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress = NULL);
+ download_async_handle download_async(const std::string &path, const std::string &url, std::function<void(const std::string&, const std::string&, bool)> result, std::function<bool(const std::string&, const std::string&, size_t, ssize_t)> progress = NULL);
+ bool download_error(const download_async_handle &h);
+ bool download_finished(const download_async_handle &h);
+ bool download_wait(const download_async_handle &h);
+ bool download_cancel(const download_async_handle &h);
}
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 05b24eee0..00e7b9d80 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -529,7 +529,7 @@ namespace cryptonote
default_decimal_point = decimal_point;
break;
default:
- ASSERT_MES_AND_THROW("Invalid decimal point specificatin: " << decimal_point);
+ ASSERT_MES_AND_THROW("Invalid decimal point specification: " << decimal_point);
}
}
//---------------------------------------------------------------
@@ -555,7 +555,7 @@ namespace cryptonote
case 0:
return "piconero";
default:
- ASSERT_MES_AND_THROW("Invalid decimal point specificatin: " << default_decimal_point);
+ ASSERT_MES_AND_THROW("Invalid decimal point specification: " << default_decimal_point);
}
}
//---------------------------------------------------------------
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index 1bc7c6269..d1036a1de 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -128,6 +128,7 @@
#define THREAD_STACK_SIZE 5 * 1024 * 1024
#define HF_VERSION_DYNAMIC_FEE 4
+#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
// New constants are intended to go here
namespace config
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index a65af3317..0713274a6 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -2796,6 +2796,19 @@ void Blockchain::check_ring_signature(const crypto::hash &tx_prefix_hash, const
}
//------------------------------------------------------------------
+static uint64_t get_fee_quantization_mask()
+{
+ static uint64_t mask = 0;
+ if (mask == 0)
+ {
+ mask = 1;
+ for (size_t n = PER_KB_FEE_QUANTIZATION_DECIMALS; n < CRYPTONOTE_DISPLAY_DECIMAL_POINT; ++n)
+ mask *= 10;
+ }
+ return mask;
+}
+
+//------------------------------------------------------------------
uint64_t Blockchain::get_dynamic_per_kb_fee(uint64_t block_reward, size_t median_block_size)
{
if (median_block_size < CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2)
@@ -2810,7 +2823,12 @@ uint64_t Blockchain::get_dynamic_per_kb_fee(uint64_t block_reward, size_t median
div128_32(hi, lo, 1000000, &hi, &lo);
assert(hi == 0);
- return lo;
+ // quantize fee up to 8 decimals
+ uint64_t mask = get_fee_quantization_mask();
+ uint64_t qlo = (lo + mask - 1) / mask * mask;
+ MDEBUG("lo " << print_money(lo) << ", qlo " << print_money(qlo) << ", mask " << mask);
+
+ return qlo;
}
//------------------------------------------------------------------
@@ -3998,7 +4016,7 @@ void Blockchain::cancel()
static const char expected_block_hashes_hash[] = "23d8a8c73de7b2383c72a016d9a6034e69d62dd48077d1c414e064ceab6daa94";
void Blockchain::load_compiled_in_block_hashes()
{
- if (m_fast_sync && get_blocks_dat_start(m_testnet) != nullptr)
+ if (m_fast_sync && get_blocks_dat_start(m_testnet) != nullptr && get_blocks_dat_size(m_testnet) > 0)
{
MINFO("Loading precomputed blocks (" << get_blocks_dat_size(m_testnet) << " bytes)");
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index cfe3b5441..9c5fae4ef 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -75,7 +75,8 @@ namespace cryptonote
m_target_blockchain_height(0),
m_checkpoints_path(""),
m_last_dns_checkpoints_update(0),
- m_last_json_checkpoints_update(0)
+ m_last_json_checkpoints_update(0),
+ m_update_download(0)
{
set_cryptonote_protocol(pprotocol);
}
@@ -134,6 +135,15 @@ namespace cryptonote
void core::stop()
{
m_blockchain_storage.cancel();
+
+ tools::download_async_handle handle;
+ {
+ boost::lock_guard<boost::mutex> lock(m_update_mutex);
+ handle = m_update_download;
+ m_update_download = 0;
+ }
+ if (handle)
+ tools::download_cancel(handle);
}
//-----------------------------------------------------------------------------------
void core::init_options(boost::program_options::options_description& desc)
@@ -1118,7 +1128,7 @@ namespace cryptonote
return true;
std::string url = tools::get_update_url(software, subdir, buildtag, version, true);
- MGINFO("Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash);
+ MCLOG_CYAN(el::Level::Info, "global", "Version " << version << " of " << software << " for " << buildtag << " is available: " << url << ", SHA256 hash " << hash);
if (check_updates_level == UPDATES_NOTIFY)
return true;
@@ -1133,32 +1143,55 @@ namespace cryptonote
boost::filesystem::path path(epee::string_tools::get_current_module_folder());
path /= filename;
+ boost::unique_lock<boost::mutex> lock(m_update_mutex);
+
+ if (m_update_download != 0)
+ {
+ MCDEBUG("updates", "Already downloading update");
+ return true;
+ }
+
crypto::hash file_hash;
if (!tools::sha256sum(path.string(), file_hash) || (hash != epee::string_tools::pod_to_hex(file_hash)))
{
MCDEBUG("updates", "We don't have that file already, downloading");
- if (!tools::download(path.string(), url))
- {
- MCERROR("updates", "Failed to download " << url);
- return false;
- }
- if (!tools::sha256sum(path.string(), file_hash))
- {
- MCERROR("updates", "Failed to hash " << path);
- return false;
- }
- if (hash != epee::string_tools::pod_to_hex(file_hash))
- {
- MCERROR("updates", "Download from " << url << " does not match the expected hash");
- return false;
- }
- MGINFO("New version downloaded to " << path);
+ m_last_update_length = 0;
+ m_update_download = tools::download_async(path.string(), url, [this, hash](const std::string &path, const std::string &uri, bool success) {
+ if (success)
+ {
+ crypto::hash file_hash;
+ if (!tools::sha256sum(path, file_hash))
+ {
+ MCERROR("updates", "Failed to hash " << path);
+ }
+ if (hash != epee::string_tools::pod_to_hex(file_hash))
+ {
+ MCERROR("updates", "Download from " << uri << " does not match the expected hash");
+ }
+ MCLOG_CYAN(el::Level::Info, "updates", "New version downloaded to " << path);
+ }
+ else
+ {
+ MCERROR("updates", "Failed to download " << uri);
+ }
+ boost::unique_lock<boost::mutex> lock(m_update_mutex);
+ m_update_download = 0;
+ }, [this](const std::string &path, const std::string &uri, size_t length, ssize_t content_length) {
+ if (length >= m_last_update_length + 1024 * 1024 * 10)
+ {
+ m_last_update_length = length;
+ MCDEBUG("updates", "Downloaded " << length << "/" << (content_length ? std::to_string(content_length) : "unknown"));
+ }
+ return true;
+ });
}
else
{
MCDEBUG("updates", "We already have " << path << " with expected hash");
}
+ lock.unlock();
+
if (check_updates_level == UPDATES_DOWNLOAD)
return true;
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 7323bef29..02d58691d 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -39,6 +39,7 @@
#include "p2p/net_node_common.h"
#include "cryptonote_protocol/cryptonote_protocol_handler_common.h"
#include "storages/portable_storage_template_helper.h"
+#include "common/download.h"
#include "tx_pool.h"
#include "blockchain.h"
#include "cryptonote_basic/miner.h"
@@ -844,6 +845,10 @@ namespace cryptonote
UPDATES_DOWNLOAD,
UPDATES_UPDATE,
} check_updates_level;
+
+ tools::download_async_handle m_update_download;
+ size_t m_last_update_length;
+ boost::mutex m_update_mutex;
};
}
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 3abd3a99a..e943c961d 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -671,9 +671,15 @@ namespace cryptonote
// Skip transactions that are not ready to be
// included into the blockchain or that are
// missing key images
- if (!is_transaction_ready_to_go(tx_it->second) || have_key_images(k_images, tx_it->second.tx))
+ if (!is_transaction_ready_to_go(tx_it->second))
{
- LOG_PRINT_L2(" not ready to go, or key images already seen");
+ LOG_PRINT_L2(" not ready to go");
+ sorted_it++;
+ continue;
+ }
+ if (have_key_images(k_images, tx_it->second.tx))
+ {
+ LOG_PRINT_L2(" key images already seen");
sorted_it++;
continue;
}
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index 61ef328ba..649823a59 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -29,9 +29,9 @@
set(blocksdat "")
if(PER_BLOCK_CHECKPOINT)
if(APPLE)
- add_custom_command(OUTPUT blocksdat.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && touch stub.c && ${CMAKE_C_COMPILER} -o stub.o -c stub.c COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && ${CMAKE_LINKER} -r -sectcreate __DATA __blocks_dat ../blocks/checkpoints.dat -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o stub.o && rm -f stub.*)
else()
- add_custom_command(OUTPUT blocksdat.o COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
+ add_custom_command(OUTPUT blocksdat.o MAIN_DEPENDENCY ../blocks/checkpoints.dat COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && cp ../blocks/checkpoints.dat blocks.dat && ${CMAKE_LINKER} -r -b binary -o ${CMAKE_CURRENT_BINARY_DIR}/blocksdat.o blocks.dat && rm -f blocks.dat)
endif()
set(blocksdat "blocksdat.o")
endif()
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index b114f77ae..9f7e8aa38 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1491,8 +1491,8 @@ namespace cryptonote
bool core_rpc_server::on_update(const COMMAND_RPC_UPDATE::request& req, COMMAND_RPC_UPDATE::response& res)
{
static const char software[] = "monero";
-#ifdef BUILDTAG
- static const char buildtag[] = BOOST_PP_STRINGIZE(BUILDTAG);
+#ifdef BUILD_TAG
+ static const char buildtag[] = BOOST_PP_STRINGIZE(BUILD_TAG);
#else
static const char buildtag[] = "source";
#endif
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 4b5a36c83..727103fa8 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -380,9 +380,9 @@ bool simple_wallet::change_password(const std::vector<std::string> &args)
return false;
}
- // prompts for a new password, this is not a new wallet so pass in false.
- const auto pwd_container = tools::wallet2::password_prompt(false);
-
+ // prompts for a new password, pass true to verify the password
+ const auto pwd_container = tools::wallet2::password_prompt(true);
+
try
{
m_wallet->rewrite(m_wallet_file, pwd_container->password());
@@ -676,6 +676,7 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("export_outputs", boost::bind(&simple_wallet::export_outputs, this, _1), tr("Export a set of outputs owned by this wallet"));
m_cmd_binder.set_handler("import_outputs", boost::bind(&simple_wallet::import_outputs, this, _1), tr("Import set of outputs owned by this wallet"));
m_cmd_binder.set_handler("show_transfer", boost::bind(&simple_wallet::show_transfer, this, _1), tr("Show information about a transfer to/from this address"));
+ m_cmd_binder.set_handler("password", boost::bind(&simple_wallet::change_password, this, _1), tr("Change wallet password"));
m_cmd_binder.set_handler("help", boost::bind(&simple_wallet::help, this, _1), tr("Show this help"));
}
//----------------------------------------------------------------------------------------------------
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 888c158c5..7ae2ce074 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -452,10 +452,10 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.restricted);
}
-boost::optional<password_container> wallet2::password_prompt(const bool is_new_wallet)
+boost::optional<password_container> wallet2::password_prompt(const bool new_password)
{
auto pwd_container = tools::password_container::prompt(
- is_new_wallet, (is_new_wallet ? tr("Enter a password for your new wallet") : tr("Wallet password"))
+ new_password, (new_password ? tr("Enter new wallet password") : tr("Wallet password"))
);
if (!pwd_container)
{
@@ -1029,7 +1029,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
payment.m_unlock_time = tx.unlock_time;
payment.m_timestamp = ts;
if (pool) {
- m_unconfirmed_payments.emplace(txid, payment);
+ m_unconfirmed_payments.emplace(payment_id, payment);
if (0 != m_callback)
m_callback->on_unconfirmed_money_received(height, txid, tx, payment.m_amount);
}
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 416b7ea69..ddc237f1b 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -114,7 +114,7 @@ namespace tools
static void init_options(boost::program_options::options_description& desc_params);
//! \return Password retrieved from prompt. Logs error on failure.
- static boost::optional<password_container> password_prompt(const bool is_new_wallet);
+ static boost::optional<password_container> password_prompt(const bool new_password);
//! Uses stdin and stdout. Returns a wallet2 if no errors.
static std::unique_ptr<wallet2> make_from_json(const boost::program_options::variables_map& vm, const std::string& json_file);
@@ -456,7 +456,14 @@ namespace tools
a & m_tx_notes;
if(ver < 13)
return;
- a & m_unconfirmed_payments;
+ if (ver < 17)
+ {
+ // we're loading an old version, where m_unconfirmed_payments was a std::map
+ std::unordered_map<crypto::hash, payment_details> m;
+ a & m;
+ for (std::unordered_map<crypto::hash, payment_details>::const_iterator i = m.begin(); i != m.end(); ++i)
+ m_unconfirmed_payments.insert(*i);
+ }
if(ver < 14)
return;
if(ver < 15)
@@ -475,6 +482,9 @@ namespace tools
if(ver < 16)
return;
a & m_address_book;
+ if(ver < 17)
+ return;
+ a & m_unconfirmed_payments;
}
/*!
@@ -633,7 +643,7 @@ namespace tools
std::atomic<uint64_t> m_local_bc_height; //temporary workaround
std::unordered_map<crypto::hash, unconfirmed_transfer_details> m_unconfirmed_txs;
std::unordered_map<crypto::hash, confirmed_transfer_details> m_confirmed_txs;
- std::unordered_map<crypto::hash, payment_details> m_unconfirmed_payments;
+ std::unordered_multimap<crypto::hash, payment_details> m_unconfirmed_payments;
std::unordered_map<crypto::hash, crypto::secret_key> m_tx_keys;
transfer_container m_transfers;
@@ -668,7 +678,7 @@ namespace tools
NodeRPCProxy m_node_rpc_proxy;
};
}
-BOOST_CLASS_VERSION(tools::wallet2, 16)
+BOOST_CLASS_VERSION(tools::wallet2, 17)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 7)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6)
diff --git a/tests/unit_tests/fee.cpp b/tests/unit_tests/fee.cpp
index 8cceac775..7026aec5c 100644
--- a/tests/unit_tests/fee.cpp
+++ b/tests/unit_tests/fee.cpp
@@ -36,6 +36,18 @@ using namespace cryptonote;
namespace
{
+ static uint64_t clamp_fee(uint64_t fee)
+ {
+ static uint64_t mask = 0;
+ if (mask == 0)
+ {
+ mask = 1;
+ for (size_t n = PER_KB_FEE_QUANTIZATION_DECIMALS; n < CRYPTONOTE_DISPLAY_DECIMAL_POINT; ++n)
+ mask *= 10;
+ }
+ return (fee + mask - 1) / mask * mask;
+ }
+
//--------------------------------------------------------------------------------------------------------------------
class fee : public ::testing::Test
{
@@ -46,46 +58,46 @@ namespace
TEST_F(fee, 10xmr)
{
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 and lower are clamped
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2), 2000000000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2), 2000000000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100), 2000000000);
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2), clamp_fee(2000000000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2), clamp_fee(2000000000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100), clamp_fee(2000000000));
ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, 1), 2000000000);
// higher is inverse proportional
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2), 2000000000 / 2);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10), 2000000000 / 10);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000), 2000000000 / 1000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull), 2000000000 / 20000);
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2), clamp_fee(2000000000 / 2));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10), clamp_fee(2000000000 / 10));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000), clamp_fee(2000000000 / 1000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(10000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull), clamp_fee(2000000000 / 20000));
}
TEST_F(fee, 1xmr)
{
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 and lower are clamped
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2), 200000000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2), 200000000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100), 200000000);
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2), clamp_fee(200000000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2), clamp_fee(200000000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100), clamp_fee(200000000));
ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, 1), 200000000);
// higher is inverse proportional
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2), 200000000 / 2);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10), 200000000 / 10);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000), 200000000 / 1000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull), 200000000 / 20000);
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2), clamp_fee(200000000 / 2));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10), clamp_fee(200000000 / 10));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000), clamp_fee(200000000 / 1000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(1000000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull), clamp_fee(200000000 / 20000));
}
TEST_F(fee, dot3xmr)
{
// CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 and lower are clamped
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2), 60000000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2), 60000000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100), 60000000);
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2), clamp_fee(60000000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 2), clamp_fee(60000000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 / 100), clamp_fee(60000000));
ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, 1), 60000000);
// higher is inverse proportional
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2), 60000000 / 2);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10), 60000000 / 10);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000), 60000000 / 1000);
- ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull), 60000000 / 20000);
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2), clamp_fee(60000000 / 2));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10), clamp_fee(60000000 / 10));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000), clamp_fee(60000000 / 1000));
+ ASSERT_EQ(Blockchain::get_dynamic_per_kb_fee(300000000000, CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull), clamp_fee(60000000 / 20000));
}
static bool is_more_or_less(double x, double y)
@@ -109,7 +121,8 @@ namespace
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 2,
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 10,
CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 1000,
- CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull
+ // with clamping, the formula does not hold for such large blocks and small fees
+ // CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V2 * 20000ull
};
for (uint64_t block_reward: block_rewards)