Skip to content

Commit f7008ea

Browse files
committed
Fixed CostModel range check for different versions of plutus
1 parent 4e4f12e commit f7008ea

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

rust/src/plutus.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ impl ConstrPlutusData {
200200
}
201201
}
202202

203-
const COST_MODEL_OP_COUNT: usize = 166;
204-
205203
#[wasm_bindgen]
206204
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
207205
pub struct CostModel(Vec<Int>);
@@ -210,26 +208,35 @@ to_from_bytes!(CostModel);
210208

211209
#[wasm_bindgen]
212210
impl CostModel {
211+
212+
#[deprecated(since = "11.0.0", note="Use `.new_with_length`")]
213213
pub fn new() -> Self {
214-
let mut costs = Vec::with_capacity(COST_MODEL_OP_COUNT);
215-
for _ in 0 .. COST_MODEL_OP_COUNT {
214+
Self::new_with_length(TxBuilderConstants::PLUTUS_V1_OP_COUNT)
215+
}
216+
217+
/// Creates a new CostModel instance with the specified underlying length
218+
pub fn new_with_length(len: usize) -> Self {
219+
let mut costs = Vec::with_capacity(len);
220+
for _ in 0 .. len {
216221
costs.push(Int::new_i32(0));
217222
}
218223
Self(costs)
219224
}
220225

221226
pub fn set(&mut self, operation: usize, cost: &Int) -> Result<Int, JsError> {
222-
if operation >= COST_MODEL_OP_COUNT {
223-
return Err(JsError::from_str(&format!("CostModel operation {} out of bounds. Max is {}", operation, COST_MODEL_OP_COUNT)));
227+
let max = self.0.len();
228+
if operation >= max {
229+
return Err(JsError::from_str(&format!("CostModel operation {} out of bounds. Max is {}", operation, max)));
224230
}
225231
let old = self.0[operation].clone();
226232
self.0[operation] = cost.clone();
227233
Ok(old)
228234
}
229235

230236
pub fn get(&self, operation: usize) -> Result<Int, JsError> {
231-
if operation >= COST_MODEL_OP_COUNT {
232-
return Err(JsError::from_str(&format!("CostModel operation {} out of bounds. Max is {}", operation, COST_MODEL_OP_COUNT)));
237+
let max = self.0.len();
238+
if operation >= max {
239+
return Err(JsError::from_str(&format!("CostModel operation {} out of bounds. Max is {}", operation, max)));
233240
}
234241
Ok(self.0[operation].clone())
235242
}
@@ -794,6 +801,7 @@ impl Strings {
794801
// Serialization
795802

796803
use std::io::{SeekFrom};
804+
use crate::tx_builder_constants::TxBuilderConstants;
797805

798806

799807
impl cbor_event::se::Serialize for PlutusScript {
@@ -898,7 +906,7 @@ impl Deserialize for ConstrPlutusData {
898906

899907
impl cbor_event::se::Serialize for CostModel {
900908
fn serialize<'se, W: Write>(&self, serializer: &'se mut Serializer<W>) -> cbor_event::Result<&'se mut Serializer<W>> {
901-
serializer.write_array(cbor_event::Len::Len(COST_MODEL_OP_COUNT as u64))?;
909+
serializer.write_array(cbor_event::Len::Len(self.0.len() as u64))?;
902910
for cost in &self.0 {
903911
cost.serialize(serializer)?;
904912
}
@@ -918,10 +926,12 @@ impl Deserialize for CostModel {
918926
}
919927
arr.push(Int::deserialize(raw)?);
920928
}
921-
if arr.len() != COST_MODEL_OP_COUNT {
929+
let min = TxBuilderConstants::PLUTUS_V1_OP_COUNT;
930+
let max = TxBuilderConstants::PLUTUS_V2_OP_COUNT;
931+
if arr.len() != min && arr.len() != max {
922932
return Err(DeserializeFailure::OutOfRange{
923-
min: COST_MODEL_OP_COUNT,
924-
max: COST_MODEL_OP_COUNT,
933+
min,
934+
max,
925935
found: arr.len()
926936
}.into());
927937
}
@@ -1574,4 +1584,10 @@ mod tests {
15741584
Language::new_plutus_v2(),
15751585
);
15761586
}
1587+
1588+
#[test]
1589+
fn test_cost_model_roundtrip() {
1590+
let costmodels = TxBuilderConstants::plutus_vasil_cost_models();
1591+
assert_eq!(costmodels, Costmdls::from_bytes(costmodels.to_bytes()).unwrap());
1592+
}
15771593
}

rust/src/tx_builder.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,6 @@ impl TransactionBuilder {
15931593

15941594
#[cfg(test)]
15951595
mod tests {
1596-
use itertools::Itertools;
15971596
use super::*;
15981597
use fees::*;
15991598
use crate::fakes::{fake_base_address, fake_bytes_32, fake_key_hash, fake_tx_hash, fake_tx_input, fake_tx_input2, fake_value, fake_value2};
@@ -5901,7 +5900,7 @@ mod tests {
59015900
let fake_out = TransactionOutput::new(&collateral_return_address, &possible_ret);
59025901
let min_ada = min_ada_for_output(&fake_out, &tx_builder.config.utxo_cost()).unwrap();
59035902

5904-
let mut total_collateral_value = to_bignum(collateral_input_value).checked_sub(&min_ada).unwrap();
5903+
let total_collateral_value = to_bignum(collateral_input_value).checked_sub(&min_ada).unwrap();
59055904

59065905
tx_builder.set_total_collateral_and_return(
59075906
&total_collateral_value,
@@ -5923,8 +5922,6 @@ mod tests {
59235922
let mut tx_builder = create_reallistic_tx_builder();
59245923
tx_builder.set_fee(&to_bignum(123456));
59255924

5926-
let masset = fake_multiasset(123);
5927-
59285925
let mut inp = TxInputsBuilder::new();
59295926
let collateral_input_value = 2_000_000;
59305927
inp.add_input(

rust/src/tx_builder_constants.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ pub struct TxBuilderConstants();
1212
#[wasm_bindgen]
1313
impl TxBuilderConstants {
1414

15+
pub const PLUTUS_V1_OP_COUNT: usize = 166;
16+
pub const PLUTUS_V2_OP_COUNT: usize = 175;
17+
1518
pub fn plutus_default_cost_models() -> Costmdls {
1619
TxBuilderConstants::plutus_alonzo_cost_models()
1720
}

0 commit comments

Comments
 (0)