diff options
Diffstat (limited to 'src/cryptonote_basic')
-rw-r--r-- | src/cryptonote_basic/cryptonote_basic_impl.cpp | 7 | ||||
-rw-r--r-- | src/cryptonote_basic/cryptonote_format_utils.cpp | 76 | ||||
-rw-r--r-- | src/cryptonote_basic/cryptonote_format_utils.h | 1 | ||||
-rw-r--r-- | src/cryptonote_basic/miner.cpp | 4 | ||||
-rw-r--r-- | src/cryptonote_basic/verification_context.h | 1 |
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 }; } |