chore: Move fee logic out of primitives (#174)
This commit is contained in:
parent
9caa176785
commit
90fa3b02f0
6 changed files with 93 additions and 76 deletions
|
|
@ -1,73 +0,0 @@
|
||||||
use crate::Error;
|
|
||||||
|
|
||||||
use super::TxPayload;
|
|
||||||
use pallas_codec::minicbor::to_vec;
|
|
||||||
|
|
||||||
pub struct PolicyParams {
|
|
||||||
constant: u64,
|
|
||||||
size_coeficient: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PolicyParams {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
constant: 155_381_000_000_000u64,
|
|
||||||
size_coeficient: 43_946_000_000u64,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_linear_fee_policy(tx_size: u64, params: &PolicyParams) -> u64 {
|
|
||||||
println!("tx size: {}", tx_size);
|
|
||||||
let nanos = params.constant + (tx_size * params.size_coeficient);
|
|
||||||
|
|
||||||
let loves = nanos / 1_000_000_000;
|
|
||||||
|
|
||||||
let rem = match nanos % 1_000_000_000 {
|
|
||||||
0 => 0u64,
|
|
||||||
_ => 1u64,
|
|
||||||
};
|
|
||||||
|
|
||||||
loves + rem
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TxPayload {
|
|
||||||
pub fn compute_fee(&self, params: &PolicyParams) -> Result<u64, Error> {
|
|
||||||
let tx_size = to_vec(&self)?.len();
|
|
||||||
let fee = compute_linear_fee_policy(tx_size as u64, params);
|
|
||||||
|
|
||||||
Ok(fee)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn compute_fee_with_defaults(&self) -> Result<u64, Error> {
|
|
||||||
self.compute_fee(&PolicyParams::default())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use pallas_codec::minicbor;
|
|
||||||
|
|
||||||
use crate::byron::Block;
|
|
||||||
|
|
||||||
type BlockWrapper = (u16, Block);
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn known_fee_matches() {
|
|
||||||
// TODO: expand this test to include more test blocks
|
|
||||||
let block_idx = 1;
|
|
||||||
let block_str = include_str!("../../../test_data/byron4.block");
|
|
||||||
|
|
||||||
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
|
|
||||||
let (_, block): BlockWrapper = minicbor::decode(&block_bytes[..])
|
|
||||||
.expect(&format!("error decoding cbor for file {}", block_idx));
|
|
||||||
|
|
||||||
// don't want to pass if we don't have tx in the block
|
|
||||||
assert!(block.body.tx_payload.len() > 0);
|
|
||||||
|
|
||||||
for tx in block.body.tx_payload.iter().take(1) {
|
|
||||||
let fee = tx.compute_fee_with_defaults().unwrap();
|
|
||||||
assert_eq!(fee, 171070);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
//! Ledger primitives and cbor codec for the Byron era
|
//! Ledger primitives and cbor codec for the Byron era
|
||||||
|
|
||||||
mod fees;
|
|
||||||
mod model;
|
mod model;
|
||||||
|
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
|
|
|
||||||
|
|
@ -17,3 +17,6 @@ pallas-crypto = { version = "0.13.0", path = "../pallas-crypto" }
|
||||||
pallas-codec = { version = "0.13.0", path = "../pallas-codec" }
|
pallas-codec = { version = "0.13.0", path = "../pallas-codec" }
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
thiserror = "1.0.31"
|
thiserror = "1.0.31"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
unstable = []
|
||||||
|
|
|
||||||
63
pallas-traverse/src/fees.rs
Normal file
63
pallas-traverse/src/fees.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
use pallas_codec::minicbor::to_vec;
|
||||||
|
use pallas_primitives::byron;
|
||||||
|
|
||||||
|
pub struct PolicyParams {
|
||||||
|
constant: u64,
|
||||||
|
size_coeficient: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PolicyParams {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
constant: 155_381_000_000_000u64,
|
||||||
|
size_coeficient: 43_946_000_000u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_linear_fee_policy(tx_size: u64, params: &PolicyParams) -> u64 {
|
||||||
|
let nanos = params.constant + (tx_size * params.size_coeficient);
|
||||||
|
|
||||||
|
let loves = nanos / 1_000_000_000;
|
||||||
|
|
||||||
|
let rem = match nanos % 1_000_000_000 {
|
||||||
|
0 => 0u64,
|
||||||
|
_ => 1u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
loves + rem
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_byron_fee(tx: &byron::MintedTxPayload, params: Option<&PolicyParams>) -> u64 {
|
||||||
|
let tx_size = to_vec(&tx).unwrap().len();
|
||||||
|
|
||||||
|
match params {
|
||||||
|
Some(params) => compute_linear_fee_policy(tx_size as u64, params),
|
||||||
|
None => compute_linear_fee_policy(tx_size as u64, &PolicyParams::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::compute_byron_fee;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn known_fee_matches() {
|
||||||
|
// TODO: expand this test to include more test blocks
|
||||||
|
let block_idx = 1;
|
||||||
|
let block_str = include_str!("../../test_data/byron4.block");
|
||||||
|
|
||||||
|
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
|
||||||
|
let block = crate::MultiEraBlock::decode_byron(&block_bytes).unwrap();
|
||||||
|
let txs = block.txs();
|
||||||
|
|
||||||
|
// don't want to pass if we don't have tx in the block
|
||||||
|
assert!(txs.len() > 0);
|
||||||
|
|
||||||
|
for tx in txs.iter().take(1) {
|
||||||
|
let byron = tx.as_byron().unwrap();
|
||||||
|
let fee = compute_byron_fee(&byron, None);
|
||||||
|
assert_eq!(fee, 171070);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ use pallas_primitives::{alonzo, babbage, byron};
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod cert;
|
pub mod cert;
|
||||||
pub mod era;
|
pub mod era;
|
||||||
|
pub mod fees;
|
||||||
pub mod hashes;
|
pub mod hashes;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod input;
|
pub mod input;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use crate::hashes::ToHash;
|
use std::{borrow::Cow, ops::Deref};
|
||||||
|
|
||||||
use pallas_codec::{minicbor, utils::KeepRaw};
|
use pallas_codec::{minicbor, utils::KeepRaw};
|
||||||
use pallas_crypto::hash::Hash;
|
use pallas_crypto::hash::Hash;
|
||||||
use pallas_primitives::{alonzo, babbage, byron};
|
use pallas_primitives::{alonzo, babbage, byron};
|
||||||
use std::{borrow::Cow, ops::Deref};
|
|
||||||
|
use crate::hashes::ToHash;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraSigners,
|
Era, MultiEraCert, MultiEraInput, MultiEraMeta, MultiEraMint, MultiEraOutput, MultiEraSigners,
|
||||||
|
|
@ -232,6 +234,28 @@ impl<'b> MultiEraTx<'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fee(&self) -> Option<u64> {
|
||||||
|
match self {
|
||||||
|
MultiEraTx::AlonzoCompatible(x, _) => Some(x.transaction_body.fee),
|
||||||
|
MultiEraTx::Babbage(x) => Some(x.transaction_body.fee),
|
||||||
|
MultiEraTx::Byron(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the fee or attempts to compute it
|
||||||
|
///
|
||||||
|
/// If the fee is available as part of the tx data (post-byron), this
|
||||||
|
/// function will return the existing value. For byron txs, this method
|
||||||
|
/// attempts to compute the value by using the linear fee policy.
|
||||||
|
#[cfg(feature = "unstable")]
|
||||||
|
pub fn fee_or_compute(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
MultiEraTx::AlonzoCompatible(x, _) => x.transaction_body.fee,
|
||||||
|
MultiEraTx::Babbage(x) => x.transaction_body.fee,
|
||||||
|
MultiEraTx::Byron(x) => crate::fees::compute_byron_fee(x, None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn aux_data(&self) -> Option<&KeepRaw<'_, alonzo::AuxiliaryData>> {
|
fn aux_data(&self) -> Option<&KeepRaw<'_, alonzo::AuxiliaryData>> {
|
||||||
match self {
|
match self {
|
||||||
MultiEraTx::AlonzoCompatible(x, _) => match &x.auxiliary_data {
|
MultiEraTx::AlonzoCompatible(x, _) => match &x.auxiliary_data {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue