Skip to content

Commit

Permalink
implement fix past fees RFC with fee shift since genesis (#3629)
Browse files Browse the repository at this point in the history
  • Loading branch information
tromp authored May 11, 2021
1 parent a9f1dd7 commit f51b6e1
Show file tree
Hide file tree
Showing 20 changed files with 133 additions and 203 deletions.
8 changes: 2 additions & 6 deletions api/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

use crate::chain;
use crate::core::consensus::YEAR_HEIGHT;
use crate::core::core::hash::Hashed;
use crate::core::core::merkle_proof::MerkleProof;
use crate::core::core::{FeeFields, KernelFeatures, TxKernel};
Expand Down Expand Up @@ -518,13 +517,10 @@ impl TxKernelPrintable {
relative_height,
} => (fee, relative_height.into()),
};
let height = 2 * YEAR_HEIGHT; // print as if post-HF4
let fee = fee_fields.fee(height);
let fee_shift: u8 = fee_fields.fee_shift(height);
TxKernelPrintable {
features,
fee_shift,
fee,
fee_shift: fee_fields.fee_shift(),
fee: fee_fields.fee(),
lock_height,
excess: k.excess.to_hex(),
excess_sig: (&k.excess_sig.to_raw_data()[..]).to_hex(),
Expand Down
2 changes: 1 addition & 1 deletion chain/tests/mine_nrd_kernel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ where
{
let prev = chain.head_header().unwrap();
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter().unwrap());
let fee = txs.iter().map(|x| x.fee(prev.height + 1)).sum();
let fee = txs.iter().map(|x| x.fee()).sum();
let reward =
reward::output(keychain, &ProofBuilder::new(keychain), key_id, fee, false).unwrap();

Expand Down
3 changes: 1 addition & 2 deletions chain/tests/mine_simple_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,8 +1030,7 @@ where
let proof_size = global::proofsize();
let key_id = ExtKeychainPath::new(1, key_idx, 0, 0, 0).to_identifier();

let height = prev.height + 1;
let fees = txs.iter().map(|tx| tx.fee(height)).sum();
let fees = txs.iter().map(|tx| tx.fee()).sum();
let reward =
libtx::reward::output(kc, &libtx::ProofBuilder::new(kc), &key_id, fees, false).unwrap();
let mut b = match core::core::Block::new(prev, txs, Difficulty::from_num(diff), reward) {
Expand Down
2 changes: 1 addition & 1 deletion chain/tests/nrd_validation_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ where
{
let next_header_info =
consensus::next_difficulty(prev.height, chain.difficulty_iter().unwrap());
let fee = txs.iter().map(|x| x.fee(prev.height + 1)).sum();
let fee = txs.iter().map(|x| x.fee()).sum();
let reward =
reward::output(keychain, &ProofBuilder::new(keychain), key_id, fee, false).unwrap();

Expand Down
5 changes: 2 additions & 3 deletions chain/tests/process_block_cut_through.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ where
let prev = chain.head_header().unwrap();
let next_height = prev.height + 1;
let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()?);
let fee = txs.iter().map(|x| x.fee(next_height)).sum();
let fee = txs.iter().map(|x| x.fee()).sum();
let key_id = ExtKeychainPath::new(1, next_height as u32, 0, 0, 0).to_identifier();
let reward =
reward::output(keychain, &ProofBuilder::new(keychain), &key_id, fee, false).unwrap();
Expand Down Expand Up @@ -126,9 +126,8 @@ fn process_block_cut_through() -> Result<(), chain::Error> {
.any(|output| output.commitment() == commit));

// Transaction is invalid due to cut-through.
let height = 7;
assert_eq!(
tx.validate(Weighting::AsTransaction, height),
tx.validate(Weighting::AsTransaction),
Err(transaction::Error::CutThrough),
);

Expand Down
6 changes: 3 additions & 3 deletions chain/tests/test_coinbase_maturity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fn test_coinbase_maturity() {
.unwrap();

let txs = &[coinbase_txn.clone()];
let fees = txs.iter().map(|tx| tx.fee(prev.height + 1)).sum();
let fees = txs.iter().map(|tx| tx.fee()).sum();
let reward = libtx::reward::output(&keychain, &builder, &key_id3, fees, false).unwrap();
let next_header_info =
consensus::next_difficulty(prev.height + 1, chain.difficulty_iter().unwrap());
Expand Down Expand Up @@ -192,7 +192,7 @@ fn test_coinbase_maturity() {
.unwrap();

let txs = &[coinbase_txn.clone()];
let fees = txs.iter().map(|tx| tx.fee(prev.height + 1)).sum();
let fees = txs.iter().map(|tx| tx.fee()).sum();
let reward = libtx::reward::output(&keychain, &builder, &key_id3, fees, false).unwrap();
let next_header_info =
consensus::next_difficulty(prev.height + 1, chain.difficulty_iter().unwrap());
Expand Down Expand Up @@ -261,7 +261,7 @@ fn test_coinbase_maturity() {
.unwrap();

let txs = &[coinbase_txn];
let fees = txs.iter().map(|tx| tx.fee(prev.height + 1)).sum();
let fees = txs.iter().map(|tx| tx.fee()).sum();
let next_header_info =
consensus::next_difficulty(prev.height + 1, chain.difficulty_iter().unwrap());
let reward = libtx::reward::output(&keychain, &builder, &key_id4, fees, false).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion core/src/core/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ impl Block {

/// Sum of all fees (inputs less outputs) in the block
pub fn total_fees(&self) -> u64 {
self.body.fee(self.header.height)
self.body.fee()
}

/// "Lightweight" validation that we can perform quickly during read/deserialization.
Expand Down
75 changes: 28 additions & 47 deletions core/src/core/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

//! Transactions
use crate::core::block::HeaderVersion;
use crate::core::hash::{DefaultHashable, Hashed};
use crate::core::{committed, Committed};
use crate::libtx::{aggsig, secp_ser};
Expand Down Expand Up @@ -161,21 +160,13 @@ impl FeeFields {
}

/// Extract fee_shift field
pub fn fee_shift(&self, height: u64) -> u8 {
if consensus::header_version(height) < HeaderVersion(5) {
0
} else {
((self.0 >> FeeFields::FEE_BITS) & FeeFields::FEE_SHIFT_MASK) as u8
}
pub fn fee_shift(&self) -> u8 {
((self.0 >> FeeFields::FEE_BITS) & FeeFields::FEE_SHIFT_MASK) as u8
}

/// Extract fee field
pub fn fee(&self, height: u64) -> u64 {
if consensus::header_version(height) < HeaderVersion(5) {
self.0
} else {
self.0 & FeeFields::FEE_MASK
}
pub fn fee(&self) -> u64 {
self.0 & FeeFields::FEE_MASK
}

/// Turn a zero `FeeField` into a `None`, any other value into a `Some`.
Expand Down Expand Up @@ -1031,7 +1022,7 @@ impl TransactionBody {
}

/// Total fee for a TransactionBody is the sum of fees of all fee carrying kernels.
pub fn fee(&self, height: u64) -> u64 {
pub fn fee(&self) -> u64 {
self.kernels
.iter()
.filter_map(|k| match k.features {
Expand All @@ -1040,13 +1031,11 @@ impl TransactionBody {
KernelFeatures::HeightLocked { fee, .. } => Some(fee),
KernelFeatures::NoRecentDuplicate { fee, .. } => Some(fee),
})
.fold(0, |acc, fee_fields| {
acc.saturating_add(fee_fields.fee(height))
})
.fold(0, |acc, fee_fields| acc.saturating_add(fee_fields.fee()))
}

/// fee_shift for a TransactionBody is the maximum of fee_shifts of all fee carrying kernels.
pub fn fee_shift(&self, height: u64) -> u8 {
pub fn fee_shift(&self) -> u8 {
self.kernels
.iter()
.filter_map(|k| match k.features {
Expand All @@ -1055,24 +1044,24 @@ impl TransactionBody {
KernelFeatures::HeightLocked { fee, .. } => Some(fee),
KernelFeatures::NoRecentDuplicate { fee, .. } => Some(fee),
})
.fold(0, |acc, fee_fields| max(acc, fee_fields.fee_shift(height)))
.fold(0, |acc, fee_fields| max(acc, fee_fields.fee_shift()))
}

/// Shifted fee for a TransactionBody is the sum of fees shifted right by the maximum fee_shift
/// this is used to determine whether a tx can be relayed or accepted in a mempool
/// where transactions can specify a higher block-inclusion priority as a positive shift up to 15
/// but are required to overpay the minimum required fees by a factor of 2^priority
pub fn shifted_fee(&self, height: u64) -> u64 {
self.fee(height) >> self.fee_shift(height)
pub fn shifted_fee(&self) -> u64 {
self.fee() >> self.fee_shift()
}

/// aggregate fee_fields from all appropriate kernels in TransactionBody into one, if possible
pub fn aggregate_fee_fields(&self, height: u64) -> Result<FeeFields, Error> {
FeeFields::new(self.fee_shift(height) as u64, self.fee(height))
pub fn aggregate_fee_fields(&self) -> Result<FeeFields, Error> {
FeeFields::new(self.fee_shift() as u64, self.fee())
}

fn overage(&self, height: u64) -> i64 {
self.fee(height) as i64
fn overage(&self) -> i64 {
self.fee() as i64
}

/// Calculate weight of transaction using block weighing
Expand Down Expand Up @@ -1413,23 +1402,23 @@ impl Transaction {
}

/// Total fee for a transaction is the sum of fees of all kernels.
pub fn fee(&self, height: u64) -> u64 {
self.body.fee(height)
pub fn fee(&self) -> u64 {
self.body.fee()
}

/// Shifted fee for a transaction is the sum of fees of all kernels shifted right by the maximum fee shift
pub fn shifted_fee(&self, height: u64) -> u64 {
self.body.shifted_fee(height)
pub fn shifted_fee(&self) -> u64 {
self.body.shifted_fee()
}

/// aggregate fee_fields from all appropriate kernels in transaction into one
pub fn aggregate_fee_fields(&self, height: u64) -> Result<FeeFields, Error> {
self.body.aggregate_fee_fields(height)
pub fn aggregate_fee_fields(&self) -> Result<FeeFields, Error> {
self.body.aggregate_fee_fields()
}

/// Total overage across all kernels.
pub fn overage(&self, height: u64) -> i64 {
self.body.overage(height)
pub fn overage(&self) -> i64 {
self.body.overage()
}

/// Lock height of a transaction is the max lock height of the kernels.
Expand All @@ -1451,17 +1440,17 @@ impl Transaction {
/// Validates all relevant parts of a fully built transaction. Checks the
/// excess value against the signature as well as range proofs for each
/// output.
pub fn validate(&self, weighting: Weighting, height: u64) -> Result<(), Error> {
pub fn validate(&self, weighting: Weighting) -> Result<(), Error> {
self.body.verify_features()?;
self.body.validate(weighting)?;
self.verify_kernel_sums(self.overage(height), self.offset.clone())?;
self.verify_kernel_sums(self.overage(), self.offset.clone())?;
Ok(())
}

/// Can be used to compare txs by their fee/weight ratio, aka feerate.
/// Don't use these values for anything else though due to precision multiplier.
pub fn fee_rate(&self, height: u64) -> u64 {
self.fee(height) / self.weight() as u64
pub fn fee_rate(&self) -> u64 {
self.fee() / self.weight() as u64
}

/// Calculate transaction weight
Expand All @@ -1470,16 +1459,8 @@ impl Transaction {
}

/// Transaction minimum acceptable fee
pub fn accept_fee(&self, height: u64) -> u64 {
if consensus::header_version(height) < HeaderVersion(5) {
Transaction::old_weight_by_iok(
self.body.inputs.len() as u64,
self.body.outputs.len() as u64,
self.body.kernels.len() as u64,
) * consensus::MILLI_GRIN
} else {
self.weight() * global::get_accept_fee_base()
}
pub fn accept_fee(&self) -> u64 {
self.weight() * global::get_accept_fee_base()
}

/// Old weight definition for pool acceptance
Expand Down
9 changes: 3 additions & 6 deletions core/src/libtx/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,7 @@ mod test {
)
.unwrap();

let height = 42; // arbitrary
tx.validate(Weighting::AsTransaction, height).unwrap();
tx.validate(Weighting::AsTransaction).unwrap();
}

#[test]
Expand All @@ -297,8 +296,7 @@ mod test {
)
.unwrap();

let height = 42; // arbitrary
tx.validate(Weighting::AsTransaction, height).unwrap();
tx.validate(Weighting::AsTransaction).unwrap();
}

#[test]
Expand All @@ -317,7 +315,6 @@ mod test {
)
.unwrap();

let height = 42; // arbitrary
tx.validate(Weighting::AsTransaction, height).unwrap();
tx.validate(Weighting::AsTransaction).unwrap();
}
}
4 changes: 2 additions & 2 deletions core/src/libtx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@ pub fn tx_fee(input_len: usize, output_len: usize, kernel_len: usize) -> u64 {
}

/// Transaction fee calculation given transaction
pub fn accept_fee(tx: Transaction, height: u64) -> u64 {
tx.accept_fee(height)
pub fn accept_fee(tx: Transaction) -> u64 {
tx.accept_fee()
}
5 changes: 1 addition & 4 deletions core/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,7 @@ where
K: Keychain,
B: ProofBuild,
{
let fees = txs
.iter()
.map(|tx| tx.fee(previous_header.height + 1))
.sum();
let fees = txs.iter().map(|tx| tx.fee()).sum();
let reward_output = reward::output(keychain, builder, &key_id, fees, false).unwrap();
Block::new(&previous_header, txs, Difficulty::min_dma(), reward_output).unwrap()
}
Expand Down
Loading

0 comments on commit f51b6e1

Please sign in to comment.