Skip to content

Commit

Permalink
Make tx weight safer (mimblewimble#2180)
Browse files Browse the repository at this point in the history
Currently it fails on fuzz tests. Also type conversion to i32 is
dangerous per se
  • Loading branch information
hashmap authored and ignopeverell committed Dec 18, 2018
1 parent 590ea33 commit 0d44c54
Showing 1 changed file with 18 additions and 15 deletions.
33 changes: 18 additions & 15 deletions core/src/core/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,7 @@ impl Readable for TransactionBody {

// quick block weight check before proceeding
let tx_block_weight =
TransactionBody::weight(input_len as usize, output_len as usize, kernel_len as usize)
as usize;
TransactionBody::weight(input_len as usize, output_len as usize, kernel_len as usize);

if tx_block_weight > consensus::MAX_BLOCK_WEIGHT {
return Err(ser::Error::TooLargeReadErr);
Expand Down Expand Up @@ -500,29 +499,33 @@ impl TransactionBody {
}

/// Calculate transaction weight
pub fn body_weight(&self) -> u32 {
pub fn body_weight(&self) -> usize {
TransactionBody::weight(self.inputs.len(), self.outputs.len(), self.kernels.len())
}

/// Calculate weight of transaction using block weighing
pub fn body_weight_as_block(&self) -> u32 {
pub fn body_weight_as_block(&self) -> usize {
TransactionBody::weight_as_block(self.inputs.len(), self.outputs.len(), self.kernels.len())
}

/// Calculate transaction weight from transaction details. This is non
/// consensus critical and compared to block weight, incentivizes spending
/// more outputs (to lower the fee).
pub fn weight(input_len: usize, output_len: usize, kernel_len: usize) -> u32 {
let body_weight = -(input_len as i32) + (4 * output_len as i32) + kernel_len as i32;
max(body_weight, 1) as u32
pub fn weight(input_len: usize, output_len: usize, kernel_len: usize) -> usize {
let body_weight = output_len
.saturating_mul(4)
.saturating_add(kernel_len)
.saturating_sub(input_len);
max(body_weight, 1)
}

/// Calculate transaction weight using block weighing from transaction
/// details. Consensus critical and uses consensus weight values.
pub fn weight_as_block(input_len: usize, output_len: usize, kernel_len: usize) -> u32 {
(input_len * consensus::BLOCK_INPUT_WEIGHT
+ output_len * consensus::BLOCK_OUTPUT_WEIGHT
+ kernel_len * consensus::BLOCK_KERNEL_WEIGHT) as u32
pub fn weight_as_block(input_len: usize, output_len: usize, kernel_len: usize) -> usize {
input_len
.saturating_mul(consensus::BLOCK_INPUT_WEIGHT)
.saturating_add(output_len.saturating_mul(consensus::BLOCK_OUTPUT_WEIGHT))
.saturating_add(kernel_len.saturating_mul(consensus::BLOCK_KERNEL_WEIGHT))
}

/// Lock height of a body is the max lock height of the kernels.
Expand All @@ -543,7 +546,7 @@ impl TransactionBody {
self.inputs.len(),
self.outputs.len() + reserve,
self.kernels.len() + reserve,
) as usize;
);

if tx_block_weight > consensus::MAX_BLOCK_WEIGHT {
return Err(Error::TooHeavy);
Expand Down Expand Up @@ -863,17 +866,17 @@ impl Transaction {
}

/// Calculate transaction weight
pub fn tx_weight(&self) -> u32 {
pub fn tx_weight(&self) -> usize {
self.body.body_weight()
}

/// Calculate transaction weight as a block
pub fn tx_weight_as_block(&self) -> u32 {
pub fn tx_weight_as_block(&self) -> usize {
self.body.body_weight_as_block()
}

/// Calculate transaction weight from transaction details
pub fn weight(input_len: usize, output_len: usize, kernel_len: usize) -> u32 {
pub fn weight(input_len: usize, output_len: usize, kernel_len: usize) -> usize {
TransactionBody::weight(input_len, output_len, kernel_len)
}
}
Expand Down

0 comments on commit 0d44c54

Please sign in to comment.