Skip to content

Commit

Permalink
feat(applying): check tx ex units
Browse files Browse the repository at this point in the history
  • Loading branch information
MaicoLeberle committed Jan 3, 2024
1 parent ca27bec commit d5fb08b
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 4 deletions.
23 changes: 20 additions & 3 deletions pallas-applying/src/alonzo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use pallas_addresses::{Address, ShelleyAddress, ShelleyPaymentPart};
use pallas_codec::{minicbor::encode, utils::KeepRaw};
use pallas_primitives::{
alonzo::{
MintedTx, MintedWitnessSet, NativeScript, PlutusData, PlutusScript, TransactionBody,
TransactionInput, TransactionOutput, VKeyWitness, Value,
MintedTx, MintedWitnessSet, NativeScript, PlutusData, PlutusScript, Redeemer,
TransactionBody, TransactionInput, TransactionOutput, VKeyWitness, Value,
},
byron::TxOut,
};
Expand Down Expand Up @@ -376,7 +376,24 @@ fn check_tx_size(_size: &u64, _prot_pps: &AlonzoProtParams) -> ValidationResult

// The number of execution units of the transaction should not exceed the
// maximum allowed.
fn check_tx_ex_units(_mtx: &MintedTx, _prot_pps: &AlonzoProtParams) -> ValidationResult {
fn check_tx_ex_units(mtx: &MintedTx, prot_pps: &AlonzoProtParams) -> ValidationResult {
let tx_wits: &MintedWitnessSet = &mtx.transaction_witness_set;
if presence_of_plutus_scripts(mtx) {
match &tx_wits.redeemer {
Some(redeemers_vec) => {
let mut steps: u64 = 0;
let mut mem: u32 = 0;
for Redeemer { ex_units, .. } in redeemers_vec {
mem += ex_units.mem;
steps += ex_units.steps;
}
if mem > prot_pps.max_tx_ex_mem || steps > prot_pps.max_tx_ex_steps {
return Err(Alonzo(TxExUnitsExceeded));
}
}
None => return Err(Alonzo(RedeemerMissing)),
}
}
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion pallas-applying/src/utils/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub struct AlonzoProtParams {
pub languages: Vec<Language>,
pub max_block_ex_mem: u64,
pub max_block_ex_steps: u64,
pub max_tx_ex_mem: u64,
pub max_tx_ex_mem: u32,
pub max_tx_ex_steps: u64,
pub max_val_size: u64,
pub collateral_percent: u64,
Expand Down
2 changes: 2 additions & 0 deletions pallas-applying/src/utils/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub enum AlonzoError {
OutputMinLovelace,
OutputWrongNetworkID,
TxWrongNetworkID,
RedeemerMissing,
TxExUnitsExceeded,
}

pub type ValidationResult = Result<(), ValidationError>;
111 changes: 111 additions & 0 deletions pallas-applying/tests/alonzo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,4 +1220,115 @@ mod alonzo_tests {
},
}
}

#[test]
// Same as successful_mainnet_tx_with_plutus_script, except that
fn tx_ex_units_exceeded() {
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/alonzo2.tx"));
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Alonzo);
let mut utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
&mtx.transaction_body,
&[
(
// (tx hash, tx output index):
// (117325a52d60be3a1e4072af39d9e630bf61ce59d315d6c1bf4c4d140f8066ea, 0)
String::from(include_str!("../../test_data/alonzo2.0.address")),
Value::Multiasset(
1724100,
KeyValuePairs::from(Vec::from([(
Hash::<28>::new([
176, 1, 7, 107, 52, 168, 126, 125, 72, 236, 70, 112, 58, 111, 80,
249, 50, 137, 88, 42, 217, 189, 190, 255, 127, 30, 50, 149,
]),
KeyValuePairs::from(Vec::from([(
Bytes::from(hex::decode("4879706562656173747332343233").unwrap()),
1,
)])),
)])),
),
None,
),
(
// (tx hash, tx output index):
// (d2f9764fa93ae5bcabbb65c7a2f97d1e31188064ae3d2ba1462114453928dd99, 0)
String::from(include_str!("../../test_data/alonzo2.1.address")),
Value::Coin(20292207),
None,
),
(
// (tx hash, tx output index):
// (9fab354c2825376a943e505d13a3861e4d9ad3e177028d7bb2bbabce5453fa11, 0)
String::from(include_str!("../../test_data/alonzo2.2.address")),
Value::Coin(20292207),
None,
),
(
// (tx hash, tx output index):
// (3077a999b1d22cb1a4e5ee485adbde6a4596704a96384fbc9727028b8b28ba47, 0)
String::from(include_str!("../../test_data/alonzo2.3.address")),
Value::Coin(29792207),
None,
),
(
// (tx hash, tx output index):
// (b231aca45a38add7378d2ed7a0822626fee3396821e8791a5af5926807db962d, 0)
String::from(include_str!("../../test_data/alonzo2.4.address")),
Value::Coin(29792207),
None,
),
(
// (tx hash, tx output index):
// (11579a841b3c7a64aa057c9adf993ef42520570450499b0a724c7ef706b2a435, 0)
String::from(include_str!("../../test_data/alonzo2.5.address")),
Value::Coin(61233231),
None,
),
(
// (tx hash, tx output index):
// (b857f98162b753d117464c499d53bbbfec5aa38b94bd624e295a7e3fddc77130, 0)
String::from(include_str!("../../test_data/alonzo2.6.address")),
Value::Coin(20292207),
None,
),
],
);
add_collateral(
&mtx.transaction_body,
&mut utxos,
&[(
String::from(include_str!("../../test_data/alonzo2.collateral.address")),
Value::Coin(5000000),
None,
)],
);
let env: Environment = Environment {
prot_params: MultiEraProtParams::Alonzo(AlonzoProtParams {
fee_policy: FeePolicy {
summand: 155381,
multiplier: 44,
},
max_tx_size: 16384,
languages: vec![Language::PlutusV1, Language::PlutusV2],
max_block_ex_mem: 50000000,
max_block_ex_steps: 40000000000,
max_tx_ex_mem: 4649575, // 1 lower than that of the transaction
max_tx_ex_steps: 1765246503, // 1 lower than that of the transaction
max_val_size: 5000,
collateral_percent: 150,
max_collateral_inputs: 3,
coints_per_utxo_word: 34482,
}),
prot_magic: 764824073,
block_slot: 58924928,
network_id: 1,
};
match validate(&metx, &utxos, &env) {
Ok(()) => assert!(false, "Transaction ex units should be below maximum"),
Err(err) => match err {
Alonzo(TxExUnitsExceeded) => (),
_ => assert!(false, "Unexpected error ({:?})", err),
},
}
}
}

0 comments on commit d5fb08b

Please sign in to comment.