aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_basic/cryptonote_format_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_basic/cryptonote_format_utils.cpp')
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp58
1 files changed, 46 insertions, 12 deletions
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 524cbf7ae..f1a5c4d94 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -142,24 +142,27 @@ namespace cryptonote
const bool bulletproof = rct::is_rct_bulletproof(rv.type);
if (bulletproof)
{
- if (rct::n_bulletproof_amounts(rv.p.bulletproofs) != tx.vout.size())
+ if (rv.p.bulletproofs.size() != 1)
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx));
return false;
}
- size_t idx = 0;
- for (size_t n = 0; n < rv.p.bulletproofs.size(); ++n)
+ if (rv.p.bulletproofs[0].L.size() < 6)
{
- //rv.p.bulletproofs[n].V.resize(1);
- //rv.p.bulletproofs[n].V[0] = rv.outPk[n].mask;
- CHECK_AND_ASSERT_MES(rv.p.bulletproofs[n].L.size() >= 6, false, "Bad bulletproofs L size"); // at least 64 bits
- const size_t n_amounts = rct::n_bulletproof_amounts(rv.p.bulletproofs[n]);
- CHECK_AND_ASSERT_MES(idx + n_amounts <= rv.outPk.size(), false, "Internal error filling out V");
- rv.p.bulletproofs[n].V.resize(n_amounts);
- rv.p.bulletproofs[n].V.clear();
- for (size_t i = 0; i < n_amounts; ++i)
- rv.p.bulletproofs[n].V[i] = rv.outPk[idx++].mask;
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs L size in tx " << get_transaction_hash(tx));
+ return false;
+ }
+ const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6);
+ if (max_outputs < tx.vout.size())
+ {
+ LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx));
+ return false;
}
+ const size_t n_amounts = tx.vout.size();
+ CHECK_AND_ASSERT_MES(n_amounts == rv.outPk.size(), false, "Internal error filling out V");
+ rv.p.bulletproofs[0].V.resize(n_amounts);
+ for (size_t i = 0; i < n_amounts; ++i)
+ rv.p.bulletproofs[0].V[i] = rv.outPk[i].mask;
}
}
}
@@ -326,6 +329,37 @@ namespace cryptonote
return string_tools::get_xtype_from_string(amount, str_amount);
}
//---------------------------------------------------------------
+ uint64_t get_transaction_weight(const transaction &tx, size_t blob_size)
+ {
+ 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(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");
+ return blob_size + bp_clawback;
+ }
+ //---------------------------------------------------------------
+ uint64_t get_transaction_weight(const transaction &tx)
+ {
+ std::ostringstream s;
+ binary_archive<true> a(s);
+ ::serialization::serialize(a, const_cast<transaction&>(tx));
+ const cryptonote::blobdata blob = s.str();
+ return get_transaction_weight(tx, blob.size());
+ }
+ //---------------------------------------------------------------
bool get_tx_fee(const transaction& tx, uint64_t & fee)
{
if (tx.version > 1)