diff --git a/blockfrost/rust/src/lib.rs b/blockfrost/rust/src/lib.rs index fac079f9..6334b869 100644 --- a/blockfrost/rust/src/lib.rs +++ b/blockfrost/rust/src/lib.rs @@ -1,7 +1,7 @@ use cml_chain::{ builders::tx_builder::TxBuilderConfigField, plutus::{CostModels, Language}, - Int, + DeserializeError, }; use std::collections::HashMap; @@ -16,6 +16,9 @@ pub enum CostModelsError { InvalidCost(Option), #[error("Invalid op count: {0}")] OpCount(usize), + // likely shouldn't happen as this would be checked earlier + #[error("Couldn't set: {0}")] + Setting(#[from] DeserializeError), } #[derive(Debug, thiserror::Error)] @@ -31,7 +34,7 @@ pub enum BlockfrostParamsParseError { pub fn parse_cost_model( serde_value: &serde_json::Value, language: Language, -) -> Result, CostModelsError> { +) -> Result, CostModelsError> { if let serde_json::Value::Object(cost_obj) = serde_value { let mut costs = vec![]; // bad idea to assume it's ordered - depends on feature enabled @@ -46,7 +49,7 @@ pub fn parse_cost_model( .get(&key) .and_then(|c| c.as_i64()) .ok_or_else(|| CostModelsError::InvalidCost(cost_obj.get(&key).cloned()))?; - costs.push(Int::from(cost)); + costs.push(cost); } Ok(costs) } else { @@ -56,7 +59,7 @@ pub fn parse_cost_model( pub fn parse_sancho_cost_model( serde_value: &serde_json::Value, -) -> Result, CostModelsError> { +) -> Result, CostModelsError> { if let serde_json::Value::Object(cost_obj) = serde_value { let mut costs = vec![]; for i in 0..CostModels::PLUTUS_V3_COUNT { @@ -66,7 +69,7 @@ pub fn parse_sancho_cost_model( .ok_or_else(|| { CostModelsError::InvalidCost(cost_obj.get(&i.to_string()).cloned()) })?; - costs.push(cml_chain::Int::from(cost)); + costs.push(cost); } Ok(costs) } else { @@ -77,25 +80,31 @@ pub fn parse_sancho_cost_model( pub fn parse_cost_models( costs: &HashMap, ) -> Result { - let mut cost_models = CostModels::new(); + let mut cost_models = CostModels::default(); if let Some(plutus_v1) = costs.get("PlutusV1") { - cost_models.plutus_v1 = Some( - parse_cost_model(plutus_v1, Language::PlutusV1) - .map_err(|e| BlockfrostParamsParseError::CostModels(e, Language::PlutusV1))?, - ); + cost_models + .set_plutus_v1( + parse_cost_model(plutus_v1, Language::PlutusV1) + .map_err(|e| BlockfrostParamsParseError::CostModels(e, Language::PlutusV1))?, + ) + .map_err(|e| BlockfrostParamsParseError::CostModels(e.into(), Language::PlutusV1))?; } if let Some(plutus_v2) = costs.get("PlutusV2") { - cost_models.plutus_v2 = Some( - parse_cost_model(plutus_v2, Language::PlutusV2) - .map_err(|e| BlockfrostParamsParseError::CostModels(e, Language::PlutusV2))?, - ); + cost_models + .set_plutus_v2( + parse_cost_model(plutus_v2, Language::PlutusV2) + .map_err(|e| BlockfrostParamsParseError::CostModels(e, Language::PlutusV2))?, + ) + .map_err(|e| BlockfrostParamsParseError::CostModels(e.into(), Language::PlutusV2))?; } // Sancho testnet has a very different format for some reason if let Some(plutus_v3) = costs.get("PlutusV3") { - cost_models.plutus_v3 = Some( - parse_sancho_cost_model(plutus_v3) - .map_err(|e| BlockfrostParamsParseError::CostModels(e, Language::PlutusV3))?, - ); + cost_models + .set_plutus_v3( + parse_sancho_cost_model(plutus_v3) + .map_err(|e| BlockfrostParamsParseError::CostModels(e, Language::PlutusV3))?, + ) + .map_err(|e| BlockfrostParamsParseError::CostModels(e.into(), Language::PlutusV3))?; } Ok(cost_models) } diff --git a/blockfrost/wasm/src/lib.rs b/blockfrost/wasm/src/lib.rs index 2a133bdd..0d0148de 100644 --- a/blockfrost/wasm/src/lib.rs +++ b/blockfrost/wasm/src/lib.rs @@ -135,7 +135,7 @@ pub fn blockfrost_make_tx_builder_cfg( #[cfg(test)] mod tests { - use cml_chain::{plutus::CostModels, Int}; + use cml_chain::plutus::{CostModels, Language}; use super::*; @@ -775,10 +775,7 @@ mod tests { 1, 196500, 453240, 220, 0, 1, 1, 806990, 30482, 4, 1927926, 82523, 4, 265318, 0, 4, 0, 85931, 32, 205665, 812, 1, 1, 41182, 32, 212342, 32, 31220, 32, 32696, 32, 43357, 32, 32247, 32, 38314, 32, 57996947, 18975, 10, - ] - .iter() - .map(|c| Int::from(*c)) - .collect(); + ]; let plutus_v2_cost_models = [ 205665i64, 812, 1, 1, 1000, 571, 0, 1, 1000, 24177, 4, 1, 1000, 32, 117366, 10475, 4, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 100, 100, @@ -792,11 +789,8 @@ mod tests { 82523, 4, 265318, 0, 4, 0, 85931, 32, 205665, 812, 1, 1, 41182, 32, 212342, 32, 31220, 32, 32696, 32, 43357, 32, 32247, 32, 38314, 32, 35892428, 10, 57996947, 18975, 10, 38887044, 32947, 10, - ] - .iter() - .map(|c| Int::from(*c)) - .collect(); - let plutus_v3_cost_models: Vec = [ + ]; + let plutus_v3_cost_models = [ 205665i64, 812, 1, 1, 1000, 571, 0, 1, 1000, 24177, 4, 1, 1000, 32, 117366, 10475, 4, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 23000, 100, 100, 100, 23000, 100, 19537, 32, 175354, 32, 46417, 4, 221973, 511, 0, 1, 89141, 32, 497525, @@ -813,13 +807,30 @@ mod tests { 3795345, 12, 889023, 1, 204237282, 23271, 36, 129165, 36, 189977790, 85902, 36, 33012864, 36, 388443360, 1, 401885761, 72, 2331379, 72, 1927926, 82523, 4, 117366, 10475, 4, - ] - .iter() - .take(CostModels::PLUTUS_V3_COUNT) - .map(|c| Int::from(*c)) - .collect(); - assert_eq!(config.cost_models.plutus_v1, Some(plutus_v1_cost_models)); - assert_eq!(config.cost_models.plutus_v2, Some(plutus_v2_cost_models)); - assert_eq!(config.cost_models.plutus_v3, Some(plutus_v3_cost_models)); + ]; + assert_eq!( + *config + .cost_models + .inner + .get(&Language::PlutusV1.into()) + .unwrap(), + plutus_v1_cost_models + ); + assert_eq!( + *config + .cost_models + .inner + .get(&Language::PlutusV2.into()) + .unwrap(), + plutus_v2_cost_models + ); + assert_eq!( + *config + .cost_models + .inner + .get(&Language::PlutusV3.into()) + .unwrap(), + plutus_v3_cost_models[..CostModels::PLUTUS_V3_COUNT] + ); } } diff --git a/chain/rust/src/plutus/utils.rs b/chain/rust/src/plutus/utils.rs index 3a3b6425..f5fceb63 100644 --- a/chain/rust/src/plutus/utils.rs +++ b/chain/rust/src/plutus/utils.rs @@ -330,6 +330,48 @@ impl CostModels { pub const PLUTUS_V2_COUNT: usize = 175; pub const PLUTUS_V3_COUNT: usize = 179; + pub fn set_plutus_v1(&mut self, costs: Vec) -> Result<(), DeserializeError> { + // on-chain there is no restriction on length but this will help users avoid problems + if costs.len() != Self::PLUTUS_V1_COUNT { + return Err(DeserializeFailure::RangeCheck { + found: costs.len() as isize, + min: Some(Self::PLUTUS_V1_COUNT as isize), + max: Some(Self::PLUTUS_V1_COUNT as isize), + } + .into()); + } + self.inner.insert(Language::PlutusV1.into(), costs); + Ok(()) + } + + pub fn set_plutus_v2(&mut self, costs: Vec) -> Result<(), DeserializeError> { + // on-chain there is no restriction on length but this will help users avoid problems + if costs.len() != Self::PLUTUS_V2_COUNT { + return Err(DeserializeFailure::RangeCheck { + found: costs.len() as isize, + min: Some(Self::PLUTUS_V2_COUNT as isize), + max: Some(Self::PLUTUS_V2_COUNT as isize), + } + .into()); + } + self.inner.insert(Language::PlutusV2.into(), costs); + Ok(()) + } + + pub fn set_plutus_v3(&mut self, costs: Vec) -> Result<(), DeserializeError> { + // on-chain there is no restriction on length but this will help users avoid problems + if costs.len() != Self::PLUTUS_V3_COUNT { + return Err(DeserializeFailure::RangeCheck { + found: costs.len() as isize, + min: Some(Self::PLUTUS_V3_COUNT as isize), + max: Some(Self::PLUTUS_V3_COUNT as isize), + } + .into()); + } + self.inner.insert(Language::PlutusV3.into(), costs); + Ok(()) + } + /// Total number of operations for the cost model of the given language pub fn op_count(language: Language) -> usize { match language { diff --git a/chain/wasm/src/plutus/utils.rs b/chain/wasm/src/plutus/utils.rs index 2b458235..86a29635 100644 --- a/chain/wasm/src/plutus/utils.rs +++ b/chain/wasm/src/plutus/utils.rs @@ -1,5 +1,5 @@ use crate::{ - plutus::{PlutusData, Redeemers}, + plutus::{CostModels, PlutusData, Redeemers}, LegacyRedeemerList, PlutusDataList, }; use cml_chain::plutus::Language; @@ -37,6 +37,21 @@ impl ConstrPlutusData { } } +#[wasm_bindgen] +impl CostModels { + pub fn set_plutus_v1(&mut self, costs: Vec) -> Result<(), JsError> { + self.0.set_plutus_v1(costs).map_err(Into::into) + } + + pub fn set_plutus_v2(&mut self, costs: Vec) -> Result<(), JsError> { + self.0.set_plutus_v2(costs).map_err(Into::into) + } + + pub fn set_plutus_v3(&mut self, costs: Vec) -> Result<(), JsError> { + self.0.set_plutus_v3(costs).map_err(Into::into) + } +} + #[derive(Clone, Debug)] #[wasm_bindgen] pub struct PlutusMap(cml_chain::plutus::PlutusMap);