aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_basic')
-rw-r--r--src/cryptonote_basic/CMakeLists.txt2
-rw-r--r--src/cryptonote_basic/account.cpp2
-rw-r--r--src/cryptonote_basic/account.h2
-rw-r--r--src/cryptonote_basic/account_boost_serialization.h2
-rw-r--r--src/cryptonote_basic/blobdatatype.h2
-rw-r--r--src/cryptonote_basic/connection_context.h2
-rw-r--r--src/cryptonote_basic/cryptonote_basic.h27
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp2
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.h2
-rw-r--r--src/cryptonote_basic/cryptonote_boost_serialization.h19
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp83
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h9
-rw-r--r--src/cryptonote_basic/cryptonote_stat_info.h5
-rw-r--r--src/cryptonote_basic/difficulty.cpp2
-rw-r--r--src/cryptonote_basic/difficulty.h2
-rw-r--r--src/cryptonote_basic/hardfork.cpp4
-rw-r--r--src/cryptonote_basic/hardfork.h2
-rw-r--r--src/cryptonote_basic/miner.cpp97
-rw-r--r--src/cryptonote_basic/miner.h11
-rw-r--r--src/cryptonote_basic/subaddress_index.h2
-rw-r--r--src/cryptonote_basic/tx_extra.h2
-rw-r--r--src/cryptonote_basic/verification_context.h2
22 files changed, 207 insertions, 76 deletions
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
index 21445959d..5bb56e083 100644
--- a/src/cryptonote_basic/CMakeLists.txt
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2014-2018, The Monero Project
+# Copyright (c) 2014-2019, The Monero Project
#
# All rights reserved.
#
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index edbc2c561..a9aec163b 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
index 021f84029..abf751b6e 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/account_boost_serialization.h b/src/cryptonote_basic/account_boost_serialization.h
index 7379d787f..320a960dc 100644
--- a/src/cryptonote_basic/account_boost_serialization.h
+++ b/src/cryptonote_basic/account_boost_serialization.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/blobdatatype.h b/src/cryptonote_basic/blobdatatype.h
index 82484c0a8..20f6b2421 100644
--- a/src/cryptonote_basic/blobdatatype.h
+++ b/src/cryptonote_basic/blobdatatype.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/connection_context.h b/src/cryptonote_basic/connection_context.h
index 6367501d2..96398a90b 100644
--- a/src/cryptonote_basic/connection_context.h
+++ b/src/cryptonote_basic/connection_context.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h
index c9c783a56..03caafbb0 100644
--- a/src/cryptonote_basic/cryptonote_basic.h
+++ b/src/cryptonote_basic/cryptonote_basic.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -152,6 +152,10 @@ namespace cryptonote
};
+ template<typename T> static inline unsigned int getpos(T &ar) { return 0; }
+ template<> inline unsigned int getpos(binary_archive<true> &ar) { return ar.stream().tellp(); }
+ template<> inline unsigned int getpos(binary_archive<false> &ar) { return ar.stream().tellg(); }
+
class transaction_prefix
{
@@ -203,9 +207,12 @@ namespace cryptonote
bool pruned;
+ std::atomic<unsigned int> unprunable_size;
+ std::atomic<unsigned int> prefix_size;
+
transaction();
- transaction(const transaction &t): transaction_prefix(t), hash_valid(false), blob_size_valid(false), signatures(t.signatures), rct_signatures(t.rct_signatures), pruned(t.pruned) { if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } }
- transaction &operator=(const transaction &t) { transaction_prefix::operator=(t); set_hash_valid(false); set_blob_size_valid(false); signatures = t.signatures; rct_signatures = t.rct_signatures; if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } pruned = t.pruned; return *this; }
+ transaction(const transaction &t): transaction_prefix(t), hash_valid(false), blob_size_valid(false), signatures(t.signatures), rct_signatures(t.rct_signatures), pruned(t.pruned), unprunable_size(t.unprunable_size.load()), prefix_size(t.prefix_size.load()) { if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } }
+ transaction &operator=(const transaction &t) { transaction_prefix::operator=(t); set_hash_valid(false); set_blob_size_valid(false); signatures = t.signatures; rct_signatures = t.rct_signatures; if (t.is_hash_valid()) { hash = t.hash; set_hash_valid(true); } if (t.is_blob_size_valid()) { blob_size = t.blob_size; set_blob_size_valid(true); } pruned = t.pruned; unprunable_size = t.unprunable_size.load(); prefix_size = t.prefix_size.load(); return *this; }
virtual ~transaction();
void set_null();
void invalidate_hashes();
@@ -223,10 +230,18 @@ namespace cryptonote
set_blob_size_valid(false);
}
+ const unsigned int start_pos = getpos(ar);
+
FIELDS(*static_cast<transaction_prefix *>(this))
+ if (std::is_same<Archive<W>, binary_archive<W>>())
+ prefix_size = getpos(ar) - start_pos;
+
if (version == 1)
{
+ if (std::is_same<Archive<W>, binary_archive<W>>())
+ unprunable_size = getpos(ar) - start_pos;
+
ar.tag("signatures");
ar.begin_array();
PREPARE_CUSTOM_VECTOR_SERIALIZATION(vin.size(), signatures);
@@ -265,6 +280,10 @@ namespace cryptonote
bool r = rct_signatures.serialize_rctsig_base(ar, vin.size(), vout.size());
if (!r || !ar.stream().good()) return false;
ar.end_object();
+
+ if (std::is_same<Archive<W>, binary_archive<W>>())
+ unprunable_size = getpos(ar) - start_pos;
+
if (!pruned && rct_signatures.type != rct::RCTTypeNull)
{
ar.tag("rctsig_prunable");
@@ -329,6 +348,8 @@ namespace cryptonote
set_hash_valid(false);
set_blob_size_valid(false);
pruned = false;
+ unprunable_size = 0;
+ prefix_size = 0;
}
inline
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index 23a5bd5bd..e336cc1d1 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h
index 0b8131a7a..036273f0e 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.h
+++ b/src/cryptonote_basic/cryptonote_basic_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h
index a4228b849..4ce9f3eeb 100644
--- a/src/cryptonote_basic/cryptonote_boost_serialization.h
+++ b/src/cryptonote_basic/cryptonote_boost_serialization.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -45,8 +45,6 @@
#include "ringct/rctTypes.h"
#include "ringct/rctOps.h"
-BOOST_CLASS_VERSION(rct::ecdhTuple, 1)
-
//namespace cryptonote {
namespace boost
{
@@ -249,19 +247,8 @@ namespace boost
template <class Archive>
inline void serialize(Archive &a, rct::ecdhTuple &x, const boost::serialization::version_type ver)
{
- if (ver < 1)
- {
- a & x.mask;
- a & x.amount;
- return;
- }
- crypto::hash8 &amount = (crypto::hash8&)x.amount;
- if (!Archive::is_saving::value)
- {
- memset(&x.mask, 0, sizeof(x.mask));
- memset(&x.amount, 0, sizeof(x.amount));
- }
- a & amount;
+ a & x.mask;
+ a & x.amount;
}
template <class Archive>
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index f6daaab95..f40464bd1 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -210,7 +210,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
- bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
+ bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash)
{
std::stringstream ss;
ss << tx_blob;
@@ -222,6 +222,13 @@ namespace cryptonote
//TODO: validate tx
get_transaction_hash(tx, tx_hash);
+ return true;
+ }
+ //---------------------------------------------------------------
+ bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash)
+ {
+ if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
+ return false;
get_transaction_prefix_hash(tx, tx_prefix_hash);
return true;
}
@@ -389,6 +396,7 @@ namespace cryptonote
for (const auto &bp: rv.p.bulletproofs)
nlr += bp.L.size() * 2;
const size_t bp_size = 32 * (9 + nlr);
+ CHECK_AND_ASSERT_THROW_MES_L1(n_outputs <= BULLETPROOF_MAX_OUTPUTS, "maximum number of outputs is " + std::to_string(BULLETPROOF_MAX_OUTPUTS) + " per transaction");
CHECK_AND_ASSERT_THROW_MES_L1(bp_base * n_padded_outputs >= bp_size, "Invalid bulletproof clawback");
const uint64_t bp_clawback = (bp_base * n_padded_outputs - bp_size) * 4 / 5;
CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow");
@@ -878,6 +886,11 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
+ void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res)
+ {
+ cn_fast_hash(blob.data(), blob.size(), res);
+ }
+ //---------------------------------------------------------------
void get_blob_hash(const blobdata& blob, crypto::hash& res)
{
cn_fast_hash(blob.data(), blob.size(), res);
@@ -946,6 +959,13 @@ namespace cryptonote
return h;
}
//---------------------------------------------------------------
+ crypto::hash get_blob_hash(const epee::span<const char>& blob)
+ {
+ crypto::hash h = null_hash;
+ get_blob_hash(blob, h);
+ return h;
+ }
+ //---------------------------------------------------------------
crypto::hash get_transaction_hash(const transaction& t)
{
crypto::hash h = null_hash;
@@ -958,26 +978,42 @@ namespace cryptonote
return get_transaction_hash(t, res, NULL);
}
//---------------------------------------------------------------
- bool calculate_transaction_prunable_hash(const transaction& t, crypto::hash& res)
+ bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res)
{
if (t.version == 1)
return false;
- transaction &tt = const_cast<transaction&>(t);
- std::stringstream ss;
- binary_archive<true> ba(ss);
- const size_t inputs = t.vin.size();
- const size_t outputs = t.vout.size();
- const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
- bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
- CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
- cryptonote::get_blob_hash(ss.str(), res);
+ static const crypto::hash empty_hash = { (char)0x70, (char)0xa4, (char)0x85, (char)0x5d, (char)0x04, (char)0xd8, (char)0xfa, (char)0x7b, (char)0x3b, (char)0x27, (char)0x82, (char)0xca, (char)0x53, (char)0xb6, (char)0x00, (char)0xe5, (char)0xc0, (char)0x03, (char)0xc7, (char)0xdc, (char)0xb2, (char)0x7d, (char)0x7e, (char)0x92, (char)0x3c, (char)0x23, (char)0xf7, (char)0x86, (char)0x01, (char)0x46, (char)0xd2, (char)0xc5 };
+ const unsigned int unprunable_size = t.unprunable_size;
+ if (blob && unprunable_size)
+ {
+ CHECK_AND_ASSERT_MES(unprunable_size <= blob->size(), false, "Inconsistent transaction unprunable and blob sizes");
+ if (blob->size() - unprunable_size == 0)
+ res = empty_hash;
+ else
+ cryptonote::get_blob_hash(epee::span<const char>(blob->data() + unprunable_size, blob->size() - unprunable_size), res);
+ }
+ else
+ {
+ transaction &tt = const_cast<transaction&>(t);
+ std::stringstream ss;
+ binary_archive<true> ba(ss);
+ const size_t inputs = t.vin.size();
+ const size_t outputs = t.vout.size();
+ const size_t mixin = t.vin.empty() ? 0 : t.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(t.vin[0]).key_offsets.size() - 1 : 0;
+ bool r = tt.rct_signatures.p.serialize_rctsig_prunable(ba, t.rct_signatures.type, inputs, outputs, mixin);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures prunable");
+ if (ss.str().empty())
+ res = empty_hash;
+ else
+ cryptonote::get_blob_hash(ss.str(), res);
+ }
return true;
}
//---------------------------------------------------------------
- crypto::hash get_transaction_prunable_hash(const transaction& t)
+ crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blobdata)
{
crypto::hash res;
- CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, res), "Failed to calculate tx prunable hash");
+ CHECK_AND_ASSERT_THROW_MES(calculate_transaction_prunable_hash(t, blobdata, res), "Failed to calculate tx prunable hash");
return res;
}
//---------------------------------------------------------------
@@ -1030,16 +1066,13 @@ namespace cryptonote
transaction &tt = const_cast<transaction&>(t);
+ const blobdata blob = tx_to_blob(t);
+ const unsigned int unprunable_size = t.unprunable_size;
+ const unsigned int prefix_size = t.prefix_size;
+
// base rct
- {
- std::stringstream ss;
- binary_archive<true> ba(ss);
- const size_t inputs = t.vin.size();
- const size_t outputs = t.vout.size();
- bool r = tt.rct_signatures.serialize_rctsig_base(ba, inputs, outputs);
- CHECK_AND_ASSERT_MES(r, false, "Failed to serialize rct signatures base");
- cryptonote::get_blob_hash(ss.str(), hashes[1]);
- }
+ CHECK_AND_ASSERT_MES(prefix_size <= unprunable_size && unprunable_size <= blob.size(), false, "Inconsistent transaction prefix, unprunable and blob sizes");
+ cryptonote::get_blob_hash(epee::span<const char>(blob.data() + prefix_size, unprunable_size - prefix_size), hashes[1]);
// prunable rct
if (t.rct_signatures.type == rct::RCTTypeNull)
@@ -1048,7 +1081,7 @@ namespace cryptonote
}
else
{
- CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, hashes[2]), false, "Failed to get tx prunable hash");
+ CHECK_AND_ASSERT_MES(calculate_transaction_prunable_hash(t, &blob, hashes[2]), false, "Failed to get tx prunable hash");
}
// the tx hash is the hash of the 3 hashes
@@ -1174,7 +1207,7 @@ namespace cryptonote
}
blobdata bd = get_block_hashing_blob(b);
const int cn_variant = b.major_version >= 7 ? b.major_version - 6 : 0;
- crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant);
+ crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant, height);
return true;
}
//---------------------------------------------------------------
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index 994978c10..40a9907be 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -51,6 +51,7 @@ namespace cryptonote
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
bool parse_and_validate_tx_prefix_from_blob(const blobdata& tx_blob, transaction_prefix& tx);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
+ bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
bool parse_and_validate_tx_base_from_blob(const blobdata& tx_blob, transaction& tx);
bool is_v1_tx(const blobdata_ref& tx_blob);
@@ -98,15 +99,17 @@ namespace cryptonote
bool generate_key_image_helper(const account_keys& ack, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, const crypto::public_key& out_key, const crypto::public_key& tx_public_key, const std::vector<crypto::public_key>& additional_tx_public_keys, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
bool generate_key_image_helper_precomp(const account_keys& ack, const crypto::public_key& out_key, const crypto::key_derivation& recv_derivation, size_t real_output_index, const subaddress_index& received_index, keypair& in_ephemeral, crypto::key_image& ki, hw::device &hwdev);
void get_blob_hash(const blobdata& blob, crypto::hash& res);
+ void get_blob_hash(const epee::span<const char>& blob, crypto::hash& res);
crypto::hash get_blob_hash(const blobdata& blob);
+ crypto::hash get_blob_hash(const epee::span<const char>& blob);
std::string short_hash_str(const crypto::hash& h);
crypto::hash get_transaction_hash(const transaction& t);
bool get_transaction_hash(const transaction& t, crypto::hash& res);
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
- bool calculate_transaction_prunable_hash(const transaction& t, crypto::hash& res);
- crypto::hash get_transaction_prunable_hash(const transaction& t);
+ bool calculate_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob, crypto::hash& res);
+ crypto::hash get_transaction_prunable_hash(const transaction& t, const cryptonote::blobdata *blob = NULL);
bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash);
diff --git a/src/cryptonote_basic/cryptonote_stat_info.h b/src/cryptonote_basic/cryptonote_stat_info.h
index c0be2144e..4cc1bc764 100644
--- a/src/cryptonote_basic/cryptonote_stat_info.h
+++ b/src/cryptonote_basic/cryptonote_stat_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -34,7 +34,7 @@
namespace cryptonote
{
- struct core_stat_info
+ struct core_stat_info_t
{
uint64_t tx_pool_size;
uint64_t blockchain_height;
@@ -50,4 +50,5 @@ namespace cryptonote
KV_SERIALIZE(top_block_id_str)
END_KV_SERIALIZE_MAP()
};
+ typedef epee::misc_utils::struct_init<core_stat_info_t> core_stat_info;
}
diff --git a/src/cryptonote_basic/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp
index 55e3e93b3..89b748a83 100644
--- a/src/cryptonote_basic/difficulty.cpp
+++ b/src/cryptonote_basic/difficulty.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/difficulty.h b/src/cryptonote_basic/difficulty.h
index b06538467..8da355b22 100644
--- a/src/cryptonote_basic/difficulty.h
+++ b/src/cryptonote_basic/difficulty.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp
index 447d79aee..ebfe45f37 100644
--- a/src/cryptonote_basic/hardfork.cpp
+++ b/src/cryptonote_basic/hardfork.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -332,7 +332,7 @@ int HardFork::get_voted_fork_index(uint64_t height) const
{
CRITICAL_REGION_LOCAL(lock);
uint32_t accumulated_votes = 0;
- for (unsigned int n = heights.size() - 1; n > current_fork_index; --n) {
+ for (int n = heights.size() - 1; n >= 0; --n) {
uint8_t v = heights[n].version;
accumulated_votes += last_versions[v];
uint32_t threshold = (window_size * heights[n].threshold + 99) / 100;
diff --git a/src/cryptonote_basic/hardfork.h b/src/cryptonote_basic/hardfork.h
index a3fc25dfa..123978b12 100644
--- a/src/cryptonote_basic/hardfork.h
+++ b/src/cryptonote_basic/hardfork.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index f4de2ed7e..6628c8448 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -73,6 +73,9 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "miner"
+#define AUTODETECT_WINDOW 10 // seconds
+#define AUTODETECT_GAIN_THRESHOLD 1.02f // 2%
+
using namespace epee;
#include "miner.h"
@@ -108,6 +111,7 @@ namespace cryptonote
m_starter_nonce(0),
m_last_hr_merge_time(0),
m_hashes(0),
+ m_total_hashes(0),
m_do_print_hashrate(false),
m_do_mining(false),
m_current_hash_rate(0),
@@ -115,7 +119,8 @@ namespace cryptonote
m_min_idle_seconds(BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS),
m_idle_threshold(BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE),
m_mining_target(BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE),
- m_miner_extra_sleep(BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS)
+ m_miner_extra_sleep(BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS),
+ m_block_reward(0)
{
}
@@ -126,12 +131,13 @@ namespace cryptonote
catch (...) { /* ignore */ }
}
//-----------------------------------------------------------------------------------------------------
- bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height)
+ bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height, uint64_t block_reward)
{
CRITICAL_REGION_LOCAL(m_template_lock);
m_template = bl;
m_diffic = di;
m_height = height;
+ m_block_reward = block_reward;
++m_template_no;
m_starter_nonce = crypto::rand<uint32_t>();
return true;
@@ -163,7 +169,7 @@ namespace cryptonote
LOG_ERROR("Failed to get_block_template(), stopping mining");
return false;
}
- set_block_template(bl, di, height);
+ set_block_template(bl, di, height, expected_reward);
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -178,7 +184,12 @@ namespace cryptonote
merge_hr();
return true;
});
-
+
+ m_autodetect_interval.do_call([&](){
+ update_autodetection();
+ return true;
+ });
+
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -209,6 +220,60 @@ namespace cryptonote
m_hashes = 0;
}
//-----------------------------------------------------------------------------------------------------
+ void miner::update_autodetection()
+ {
+ if (m_threads_autodetect.empty())
+ return;
+
+ uint64_t now = epee::misc_utils::get_ns_count();
+ uint64_t dt = now - m_threads_autodetect.back().first;
+ if (dt < AUTODETECT_WINDOW * 1000000000ull)
+ return;
+
+ // work out how many more hashes we got
+ m_threads_autodetect.back().first = dt;
+ uint64_t dh = m_total_hashes - m_threads_autodetect.back().second;
+ m_threads_autodetect.back().second = dh;
+ float hs = dh / (dt / (float)1000000000);
+ MGINFO("Mining autodetection: " << m_threads_autodetect.size() << " threads: " << hs << " H/s");
+
+ // when we don't increase by at least 2%, stop, otherwise check next
+ // if N and N+1 have mostly the same hash rate, we want to "lighter" one
+ bool found = false;
+ if (m_threads_autodetect.size() > 1)
+ {
+ int previdx = m_threads_autodetect.size() - 2;
+ float previous_hs = m_threads_autodetect[previdx].second / (m_threads_autodetect[previdx].first / (float)1000000000);
+ if (previous_hs > 0 && hs / previous_hs < AUTODETECT_GAIN_THRESHOLD)
+ {
+ m_threads_total = m_threads_autodetect.size() - 1;
+ m_threads_autodetect.clear();
+ MGINFO("Optimal number of threads seems to be " << m_threads_total);
+ found = true;
+ }
+ }
+
+ if (!found)
+ {
+ // setup one more thread
+ m_threads_autodetect.push_back({now, m_total_hashes});
+ m_threads_total = m_threads_autodetect.size();
+ }
+
+ // restart all threads
+ {
+ CRITICAL_REGION_LOCAL(m_threads_lock);
+ boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1);
+ for(boost::thread& th: m_threads)
+ th.join();
+ m_threads.clear();
+ }
+ boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0);
+ boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0);
+ for(size_t i = 0; i != m_threads_total; i++)
+ m_threads.push_back(boost::thread(m_attrs, boost::bind(&miner::worker_thread, this)));
+ }
+ //-----------------------------------------------------------------------------------------------------
void miner::init_options(boost::program_options::options_description& desc)
{
command_line::add_arg(desc, arg_extra_messages);
@@ -242,7 +307,8 @@ namespace cryptonote
}
m_config_folder_path = boost::filesystem::path(command_line::get_arg(vm, arg_extra_messages)).parent_path().string();
m_config = AUTO_VAL_INIT(m_config);
- epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME);
+ const std::string filename = m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME;
+ CHECK_AND_ASSERT_MES(epee::serialization::load_t_from_json_file(m_config, filename), false, "Failed to load data from " << filename);
MINFO("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index);
}
@@ -295,8 +361,16 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------------
bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background, bool ignore_battery)
{
+ m_block_reward = 0;
m_mine_address = adr;
m_threads_total = static_cast<uint32_t>(threads_count);
+ if (threads_count == 0)
+ {
+ m_threads_autodetect.clear();
+ m_threads_autodetect.push_back({epee::misc_utils::get_ns_count(), m_total_hashes});
+ m_threads_total = 1;
+ }
+ m_attrs = attrs;
m_starter_nonce = crypto::rand<uint32_t>();
CRITICAL_REGION_LOCAL(m_threads_lock);
if(is_mining())
@@ -318,12 +392,15 @@ namespace cryptonote
set_is_background_mining_enabled(do_background);
set_ignore_battery(ignore_battery);
- for(size_t i = 0; i != threads_count; i++)
+ for(size_t i = 0; i != m_threads_total; i++)
{
m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this)));
}
- LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" );
+ if (threads_count == 0)
+ MINFO("Mining has started, autodetecting optimal number of threads, good luck!" );
+ else
+ MINFO("Mining has started with " << threads_count << " threads, good luck!" );
if( get_is_background_mining_enabled() )
{
@@ -360,7 +437,7 @@ namespace cryptonote
if (!is_mining())
{
- MDEBUG("Not mining - nothing to stop" );
+ MTRACE("Not mining - nothing to stop" );
return true;
}
@@ -381,6 +458,7 @@ namespace cryptonote
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
m_threads.clear();
+ m_threads_autodetect.clear();
return true;
}
//-----------------------------------------------------------------------------------------------------
@@ -506,6 +584,7 @@ namespace cryptonote
}
nonce+=m_threads_total;
++m_hashes;
+ ++m_total_hashes;
}
slow_hash_free_state();
MGINFO("Miner thread stopped ["<< th_local_index << "]");
diff --git a/src/cryptonote_basic/miner.h b/src/cryptonote_basic/miner.h
index e16d9f3b8..08b1bd7f1 100644
--- a/src/cryptonote_basic/miner.h
+++ b/src/cryptonote_basic/miner.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -61,7 +61,7 @@ namespace cryptonote
~miner();
bool init(const boost::program_options::variables_map& vm, network_type nettype);
static void init_options(boost::program_options::options_description& desc);
- bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
+ bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height, uint64_t block_reward);
bool on_block_chain_update();
bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs, bool do_background = false, bool ignore_battery = false);
uint64_t get_speed() const;
@@ -85,6 +85,7 @@ namespace cryptonote
bool set_idle_threshold(uint8_t idle_threshold);
uint8_t get_mining_target() const;
bool set_mining_target(uint8_t mining_target);
+ uint64_t get_block_reward() const { return m_block_reward; }
static constexpr uint8_t BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE = 90;
static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 50;
@@ -103,6 +104,7 @@ namespace cryptonote
bool worker_thread();
bool request_block_template();
void merge_hr();
+ void update_autodetection();
struct miner_config
{
@@ -132,16 +134,20 @@ namespace cryptonote
account_public_address m_mine_address;
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
+ epee::math_helper::once_a_time_seconds<1> m_autodetect_interval;
std::vector<blobdata> m_extra_messages;
miner_config m_config;
std::string m_config_folder_path;
std::atomic<uint64_t> m_last_hr_merge_time;
std::atomic<uint64_t> m_hashes;
+ std::atomic<uint64_t> m_total_hashes;
std::atomic<uint64_t> m_current_hash_rate;
epee::critical_section m_last_hash_rates_lock;
std::list<uint64_t> m_last_hash_rates;
bool m_do_print_hashrate;
bool m_do_mining;
+ std::vector<std::pair<uint64_t, uint64_t>> m_threads_autodetect;
+ boost::thread::attributes m_attrs;
// background mining stuffs ..
@@ -164,5 +170,6 @@ namespace cryptonote
static bool get_process_time(uint64_t& total_time);
static uint8_t get_percent_of_total(uint64_t some_time, uint64_t total_time);
static boost::logic::tribool on_battery_power();
+ std::atomic<uint64_t> m_block_reward;
};
}
diff --git a/src/cryptonote_basic/subaddress_index.h b/src/cryptonote_basic/subaddress_index.h
index 9b71448f9..99933e229 100644
--- a/src/cryptonote_basic/subaddress_index.h
+++ b/src/cryptonote_basic/subaddress_index.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-2018, The Monero Project
+// Copyright (c) 2017-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/tx_extra.h b/src/cryptonote_basic/tx_extra.h
index 009e35ebe..ecb4c6040 100644
--- a/src/cryptonote_basic/tx_extra.h
+++ b/src/cryptonote_basic/tx_extra.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
diff --git a/src/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h
index 8d2b633a2..36b63f254 100644
--- a/src/cryptonote_basic/verification_context.h
+++ b/src/cryptonote_basic/verification_context.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//