aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_basic
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_basic')
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp7
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp76
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h1
-rw-r--r--src/cryptonote_basic/miner.cpp4
-rw-r--r--src/cryptonote_basic/verification_context.h1
5 files changed, 73 insertions, 16 deletions
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index d8de65b81..9bafcfc86 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
@@ -110,9 +110,6 @@ namespace cryptonote {
return false;
}
- assert(median_weight < std::numeric_limits<uint32_t>::max());
- assert(current_block_weight < std::numeric_limits<uint32_t>::max());
-
uint64_t product_hi;
// BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being
// treated as 32-bit by default.
@@ -122,8 +119,8 @@ namespace cryptonote {
uint64_t reward_hi;
uint64_t reward_lo;
- div128_32(product_hi, product_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo);
- div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo);
+ div128_64(product_hi, product_lo, median_weight, &reward_hi, &reward_lo, NULL, NULL);
+ div128_64(reward_hi, reward_lo, median_weight, &reward_hi, &reward_lo, NULL, NULL);
assert(0 == reward_hi);
assert(reward_lo < base_reward);
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 3501c66c8..138cf49f4 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -103,6 +103,26 @@ namespace cryptonote
ge_p1p1_to_p3(&A2, &tmp3);
ge_p3_tobytes(&AB, &A2);
}
+
+ uint64_t get_transaction_weight_clawback(const transaction &tx, size_t n_padded_outputs)
+ {
+ const rct::rctSig &rv = tx.rct_signatures;
+ const uint64_t bp_base = 368;
+ const size_t n_outputs = tx.vout.size();
+ if (n_padded_outputs <= 2)
+ return 0;
+ size_t nlr = 0;
+ while ((1u << nlr) < n_padded_outputs)
+ ++nlr;
+ nlr += 6;
+ const size_t bp_size = 32 * (9 + 2 * 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: bp_base " + std::to_string(bp_base) + ", n_padded_outputs "
+ + std::to_string(n_padded_outputs) + ", bp_size " + std::to_string(bp_size));
+ const uint64_t bp_clawback = (bp_base * n_padded_outputs - bp_size) * 4 / 5;
+ return bp_clawback;
+ }
+ //---------------------------------------------------------------
}
namespace cryptonote
@@ -386,27 +406,61 @@ namespace cryptonote
//---------------------------------------------------------------
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
{
+ CHECK_AND_ASSERT_MES(!tx.pruned, std::numeric_limits<uint64_t>::max(), "get_transaction_weight does not support pruned txes");
if (tx.version < 2)
return blob_size;
const rct::rctSig &rv = tx.rct_signatures;
if (!rct::is_rct_bulletproof(rv.type))
return blob_size;
- const size_t n_outputs = tx.vout.size();
- if (n_outputs <= 2)
- return blob_size;
- const uint64_t bp_base = 368;
const size_t n_padded_outputs = rct::n_bulletproof_max_amounts(rv.p.bulletproofs);
- size_t nlr = 0;
- 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;
+ uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs);
CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - blob_size, "Weight overflow");
return blob_size + bp_clawback;
}
//---------------------------------------------------------------
+ uint64_t get_pruned_transaction_weight(const transaction &tx)
+ {
+ CHECK_AND_ASSERT_MES(tx.pruned, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support non pruned txes");
+ CHECK_AND_ASSERT_MES(tx.version >= 2, std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support v1 txes");
+ CHECK_AND_ASSERT_MES(tx.rct_signatures.type >= rct::RCTTypeBulletproof2,
+ std::numeric_limits<uint64_t>::max(), "get_pruned_transaction_weight does not support older range proof types");
+ CHECK_AND_ASSERT_MES(!tx.vin.empty(), std::numeric_limits<uint64_t>::max(), "empty vin");
+ CHECK_AND_ASSERT_MES(tx.vin[0].type() == typeid(cryptonote::txin_to_key), std::numeric_limits<uint64_t>::max(), "empty vin");
+
+ // get pruned data size
+ std::ostringstream s;
+ binary_archive<true> a(s);
+ ::serialization::serialize(a, const_cast<transaction&>(tx));
+ uint64_t weight = s.str().size(), extra;
+
+ // nbps (technically varint)
+ weight += 1;
+
+ // calculate deterministic bulletproofs size (assumes canonical BP format)
+ size_t nrl = 0, n_padded_outputs;
+ while ((n_padded_outputs = (1u << nrl)) < tx.vout.size())
+ ++nrl;
+ nrl += 6;
+ extra = 32 * (9 + 2 * nrl) + 2;
+ weight += extra;
+
+ // calculate deterministic MLSAG data size
+ const size_t ring_size = boost::get<cryptonote::txin_to_key>(tx.vin[0]).key_offsets.size();
+ extra = tx.vin.size() * (ring_size * (1 + 1) * 32 + 32 /* cc */);
+ weight += extra;
+
+ // calculate deterministic pseudoOuts size
+ extra = 32 * (tx.vin.size());
+ weight += extra;
+
+ // clawback
+ uint64_t bp_clawback = get_transaction_weight_clawback(tx, n_padded_outputs);
+ CHECK_AND_ASSERT_THROW_MES_L1(bp_clawback <= std::numeric_limits<uint64_t>::max() - weight, "Weight overflow");
+ weight += bp_clawback;
+
+ return weight;
+ }
+ //---------------------------------------------------------------
uint64_t get_transaction_weight(const transaction &tx)
{
size_t blob_size;
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index 284494299..29e4def64 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -127,6 +127,7 @@ namespace cryptonote
bool parse_amount(uint64_t& amount, const std::string& str_amount);
uint64_t get_transaction_weight(const transaction &tx);
uint64_t get_transaction_weight(const transaction &tx, size_t blob_size);
+ uint64_t get_pruned_transaction_weight(const transaction &tx);
bool check_money_overflow(const transaction& tx);
bool check_outs_overflow(const transaction& tx);
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 0188bf114..c4b5c8455 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -62,7 +62,9 @@
#include <devstat.h>
#include <errno.h>
#include <fcntl.h>
+#if defined(__amd64__) || defined(__i386__) || defined(__x86_64__)
#include <machine/apm_bios.h>
+#endif
#include <stdio.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
@@ -1086,6 +1088,7 @@ namespace cryptonote
return boost::logic::tribool(boost::logic::indeterminate);
}
+#if defined(__amd64__) || defined(__i386__) || defined(__x86_64__)
apm_info info;
if( ioctl(fd, APMIO_GETINFO, &info) == -1 ) {
close(fd);
@@ -1126,6 +1129,7 @@ namespace cryptonote
LOG_ERROR("sysctlbyname(\"hw.acpi.acline\") output is unexpectedly "
<< n << " bytes instead of the expected " << sizeof(ac) << " bytes.");
return boost::logic::tribool(boost::logic::indeterminate);
+#endif
}
return boost::logic::tribool(ac == 0);
#endif
diff --git a/src/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h
index 3d7200fae..f5f663464 100644
--- a/src/cryptonote_basic/verification_context.h
+++ b/src/cryptonote_basic/verification_context.h
@@ -58,5 +58,6 @@ namespace cryptonote
bool m_marked_as_orphaned;
bool m_already_exists;
bool m_partial_block_reward;
+ bool m_bad_pow; // if bad pow, bad peer outright for DoS protection
};
}