mirror of
https://github.com/monero-project/monero.git
synced 2025-05-02 17:24:50 -04:00
v8: per byte fee, pad bulletproofs, fixed 11 ring size
This commit is contained in:
parent
869b3bf824
commit
5ffb2ff9b7
55 changed files with 1241 additions and 878 deletions
|
@ -67,7 +67,7 @@ namespace cryptonote {
|
|||
/* Cryptonote helper functions */
|
||||
/************************************************************************/
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
size_t get_min_block_size(uint8_t version)
|
||||
size_t get_min_block_weight(uint8_t version)
|
||||
{
|
||||
if (version < 2)
|
||||
return CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE_V1;
|
||||
|
@ -86,7 +86,7 @@ namespace cryptonote {
|
|||
return CRYPTONOTE_MAX_TX_SIZE;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version) {
|
||||
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version) {
|
||||
static_assert(DIFFICULTY_TARGET_V2%60==0&&DIFFICULTY_TARGET_V1%60==0,"difficulty targets must be a multiple of 60");
|
||||
const int target = version < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
|
||||
const int target_minutes = target / 60;
|
||||
|
@ -98,37 +98,37 @@ namespace cryptonote {
|
|||
base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes;
|
||||
}
|
||||
|
||||
uint64_t full_reward_zone = get_min_block_size(version);
|
||||
uint64_t full_reward_zone = get_min_block_weight(version);
|
||||
|
||||
//make it soft
|
||||
if (median_size < full_reward_zone) {
|
||||
median_size = full_reward_zone;
|
||||
if (median_weight < full_reward_zone) {
|
||||
median_weight = full_reward_zone;
|
||||
}
|
||||
|
||||
if (current_block_size <= median_size) {
|
||||
if (current_block_weight <= median_weight) {
|
||||
reward = base_reward;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(current_block_size > 2 * median_size) {
|
||||
MERROR("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size);
|
||||
if(current_block_weight > 2 * median_weight) {
|
||||
MERROR("Block cumulative weight is too big: " << current_block_weight << ", expected less than " << 2 * median_weight);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(median_size < std::numeric_limits<uint32_t>::max());
|
||||
assert(current_block_size < std::numeric_limits<uint32_t>::max());
|
||||
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.
|
||||
uint64_t multiplicand = 2 * median_size - current_block_size;
|
||||
multiplicand *= current_block_size;
|
||||
uint64_t multiplicand = 2 * median_weight - current_block_weight;
|
||||
multiplicand *= current_block_weight;
|
||||
uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi);
|
||||
|
||||
uint64_t reward_hi;
|
||||
uint64_t reward_lo;
|
||||
div128_32(product_hi, product_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo);
|
||||
div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_size), &reward_hi, &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);
|
||||
assert(0 == reward_hi);
|
||||
assert(reward_lo < base_reward);
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ namespace cryptonote {
|
|||
/************************************************************************/
|
||||
/* Cryptonote helper functions */
|
||||
/************************************************************************/
|
||||
size_t get_min_block_size(uint8_t version);
|
||||
size_t get_min_block_weight(uint8_t version);
|
||||
size_t get_max_block_size();
|
||||
size_t get_max_tx_size();
|
||||
bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version);
|
||||
bool get_block_reward(size_t median_weight, size_t current_block_weight, uint64_t already_generated_coins, uint64_t &reward, uint8_t version);
|
||||
uint8_t get_account_address_checksum(const public_address_outer_blob& bl);
|
||||
uint8_t get_account_integrated_address_checksum(const public_integrated_address_outer_blob& bl);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -117,6 +117,8 @@ namespace cryptonote
|
|||
bool check_inputs_types_supported(const transaction& tx);
|
||||
bool check_outs_valid(const transaction& tx);
|
||||
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);
|
||||
|
||||
bool check_money_overflow(const transaction& tx);
|
||||
bool check_outs_overflow(const transaction& tx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue