Update BP fee_weight

Closes https://github.com/serai-dex/serai/issues/8.
This commit is contained in:
Luke Parker 2022-08-21 10:35:10 -04:00
parent 755d021f8e
commit 60d93c4b2d
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
5 changed files with 37 additions and 33 deletions

View file

@ -11,6 +11,7 @@ use crate::{Commitment, wallet::TransactionError, serialize::*};
pub(crate) mod scalar_vector;
pub(crate) mod core;
use self::core::LOG_N;
pub(crate) mod original;
pub(crate) mod plus;
@ -28,19 +29,23 @@ pub enum Bulletproofs {
}
impl Bulletproofs {
// TODO
pub(crate) fn fee_weight(outputs: usize) -> usize {
let proofs = 6 + usize::try_from(usize::BITS - (outputs - 1).leading_zeros()).unwrap();
let len = (9 + (2 * proofs)) * 32;
pub(crate) fn fee_weight(plus: bool, outputs: usize) -> usize {
let fields = if plus { 6 } else { 9 };
let mut clawback = 0;
let padded = 1 << (proofs - 6);
if padded > 2 {
const BP_BASE: usize = 368;
clawback = ((BP_BASE * padded) - len) * 4 / 5;
}
#[allow(non_snake_case)]
let mut LR_len = usize::try_from(usize::BITS - (outputs - 1).leading_zeros()).unwrap();
let padded_outputs = 1 << LR_len;
LR_len += LOG_N;
len + clawback
let len = (fields + (2 * LR_len)) * 32;
len +
if padded_outputs <= 2 {
0
} else {
let base = ((fields + (2 * (LOG_N + 1))) * 32) / 2;
let size = (fields + (2 * LR_len)) * 32;
((base * padded_outputs) - size) * 4 / 5
}
}
pub fn prove<R: RngCore + CryptoRng>(

View file

@ -9,6 +9,7 @@ pub mod clsag;
pub mod bulletproofs;
use crate::{
Protocol,
serialize::*,
ringct::{clsag::Clsag, bulletproofs::Bulletproofs},
};
@ -86,8 +87,9 @@ impl RctPrunable {
}
}
pub(crate) fn fee_weight(ring_len: usize, inputs: usize, outputs: usize) -> usize {
1 + Bulletproofs::fee_weight(outputs) + (inputs * (Clsag::fee_weight(ring_len) + 32))
pub(crate) fn fee_weight(protocol: Protocol, inputs: usize, outputs: usize) -> usize {
1 + Bulletproofs::fee_weight(protocol.bp_plus(), outputs) +
(inputs * (Clsag::fee_weight(protocol.ring_len()) + 32))
}
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
@ -142,8 +144,8 @@ pub struct RctSignatures {
}
impl RctSignatures {
pub(crate) fn fee_weight(ring_len: usize, inputs: usize, outputs: usize) -> usize {
RctBase::fee_weight(outputs) + RctPrunable::fee_weight(ring_len, inputs, outputs)
pub(crate) fn fee_weight(protocol: Protocol, inputs: usize, outputs: usize) -> usize {
RctBase::fee_weight(outputs) + RctPrunable::fee_weight(protocol, inputs, outputs)
}
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {

View file

@ -371,8 +371,7 @@ impl Rpc {
)
.await?;
// TODO: Support time based lock times. These shouldn't be needed, and it may be painful to
// get the median time for the given height, yet we do need to in order to be complete
// TODO: https://github.com/serai-dex/serai/issues/104
outs
.outs
.iter()

View file

@ -5,7 +5,7 @@ use zeroize::Zeroize;
use curve25519_dalek::edwards::EdwardsPoint;
use crate::{
hash,
Protocol, hash,
serialize::*,
ringct::{RctPrunable, RctSignatures},
};
@ -193,9 +193,14 @@ pub struct Transaction {
}
impl Transaction {
pub(crate) fn fee_weight(ring_len: usize, inputs: usize, outputs: usize, extra: usize) -> usize {
TransactionPrefix::fee_weight(ring_len, inputs, outputs, extra) +
RctSignatures::fee_weight(ring_len, inputs, outputs)
pub(crate) fn fee_weight(
protocol: Protocol,
inputs: usize,
outputs: usize,
extra: usize,
) -> usize {
TransactionPrefix::fee_weight(protocol.ring_len(), inputs, outputs, extra) +
RctSignatures::fee_weight(protocol, inputs, outputs)
}
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {

View file

@ -212,12 +212,8 @@ impl SignableTransaction {
let extra = Extra::fee_weight(outputs);
// Calculate the fee.
let mut fee = fee_rate.calculate(Transaction::fee_weight(
protocol.ring_len(),
inputs.len(),
outputs,
extra,
));
let mut fee =
fee_rate.calculate(Transaction::fee_weight(protocol, inputs.len(), outputs, extra));
// Make sure we have enough funds
let in_amount = inputs.iter().map(|input| input.commitment.amount).sum::<u64>();
@ -229,12 +225,9 @@ impl SignableTransaction {
// If we have yet to add a change output, do so if it's economically viable
if (!change) && change_address.is_some() && (in_amount != out_amount) {
// Check even with the new fee, there's remaining funds
let change_fee = fee_rate.calculate(Transaction::fee_weight(
protocol.ring_len(),
inputs.len(),
outputs + 1,
extra,
)) - fee;
let change_fee =
fee_rate.calculate(Transaction::fee_weight(protocol, inputs.len(), outputs + 1, extra)) -
fee;
if (out_amount + change_fee) < in_amount {
change = true;
out_amount += change_fee;