From 3012a0b41dfd326377e79baf70633e77d53eb030 Mon Sep 17 00:00:00 2001 From: alessandrokonrad Date: Wed, 8 Feb 2023 13:14:26 +0100 Subject: [PATCH] Fix constructor tag range --- crates/aiken-lang/src/builder.rs | 11 +++-- crates/uplc/src/machine/runtime.rs | 70 +++++++++++++++------------- crates/uplc/src/tx/to_plutus_data.rs | 22 ++++----- 3 files changed, 54 insertions(+), 49 deletions(-) diff --git a/crates/aiken-lang/src/builder.rs b/crates/aiken-lang/src/builder.rs index 2a08c6e5..c1cac151 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -8,7 +8,7 @@ use uplc::{ Constant as UplcConstant, Name, Term, Type as UplcType, }, builtins::DefaultFunction, - machine::runtime::convert_constr_to_tag, + machine::runtime::{convert_constr_to_tag, ANY_TAG}, BigInt, Constr, KeyValuePairs, PlutusData, }; @@ -237,7 +237,7 @@ pub fn convert_type_to_data(term: Term, field_type: &Arc) -> Term, field_type: &Arc) -> Term>) -> Vec UplcConstant::Data(PlutusData::Constr(Constr { - tag: convert_constr_to_tag((*b).into()), - any_constructor: None, + tag: convert_constr_to_tag((*b).into()).unwrap_or(ANY_TAG), + any_constructor: convert_constr_to_tag((*b).into()) + .map_or(Some((*b).into()), |_| None), fields: vec![], })), UplcConstant::ProtoList(_, constants) => { diff --git a/crates/uplc/src/machine/runtime.rs b/crates/uplc/src/machine/runtime.rs index 6325b24c..cca4557c 100644 --- a/crates/uplc/src/machine/runtime.rs +++ b/crates/uplc/src/machine/runtime.rs @@ -880,9 +880,9 @@ impl DefaultFunction { .collect(); let constr_data = PlutusData::Constr(Constr { - // TODO: handle other types of constructor tags - tag: convert_constr_to_tag(*i as u64), - any_constructor: None, + tag: convert_constr_to_tag(*i as u64).unwrap_or(ANY_TAG), + any_constructor: convert_constr_to_tag(*i as u64) + .map_or(Some(*i as u64), |_| None), fields: data_list, }); @@ -959,27 +959,29 @@ impl DefaultFunction { }, DefaultFunction::UnConstrData => match args[0].as_ref() { Value::Con(con) => match con.as_ref() { - Constant::Data(PlutusData::Constr(c)) => { - Ok(Value::Con( - Constant::ProtoPair( - Type::Integer, - Type::List(Type::Data.into()), - // TODO: handle other types of constructor tags - Constant::Integer(convert_tag_to_constr(c.tag as i128)).into(), - Constant::ProtoList( - Type::Data, - c.fields - .deref() - .iter() - .map(|d| Constant::Data(d.clone())) - .collect(), - ) - .into(), + Constant::Data(PlutusData::Constr(c)) => Ok(Value::Con( + Constant::ProtoPair( + Type::Integer, + Type::List(Type::Data.into()), + Constant::Integer( + convert_tag_to_constr(c.tag) + .unwrap_or_else(|| c.any_constructor.unwrap()) + as i128, + ) + .into(), + Constant::ProtoList( + Type::Data, + c.fields + .deref() + .iter() + .map(|d| Constant::Data(d.clone())) + .collect(), ) .into(), ) - .into()) - } + .into(), + ) + .into()), v => Err(Error::DeserialisationError( "UnConstrData".to_string(), Value::Con(v.clone().into()), @@ -1126,26 +1128,28 @@ impl DefaultFunction { } } -pub fn convert_tag_to_constr(tag: i128) -> i128 { - if tag < 128 { - tag - 121 - } else if (1280..1401).contains(&tag) { - tag - 1280 +pub fn convert_tag_to_constr(tag: u64) -> Option { + if (121..=127).contains(&tag) { + Some(tag - 121) + } else if (1280..=1400).contains(&tag) { + Some(tag - 1280 + 7) } else { - todo!() + None } } -pub fn convert_constr_to_tag(constr: u64) -> u64 { - if constr < 7 { - constr + 121 - } else if constr < 128 { - constr + 1280 +pub fn convert_constr_to_tag(constr: u64) -> Option { + if (0..=6).contains(&constr) { + Some(121 + constr) + } else if (7..=127).contains(&constr) { + Some(1280 - 7 + constr) } else { - todo!() + None // 102 otherwise } } +pub static ANY_TAG: u64 = 102; + #[cfg(not(feature = "native-secp256k1"))] fn verify_ecdsa(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result, Error> { use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1}; diff --git a/crates/uplc/src/tx/to_plutus_data.rs b/crates/uplc/src/tx/to_plutus_data.rs index f8365664..e710af76 100644 --- a/crates/uplc/src/tx/to_plutus_data.rs +++ b/crates/uplc/src/tx/to_plutus_data.rs @@ -8,37 +8,37 @@ use pallas_primitives::babbage::{ }; use pallas_traverse::ComputeHash; +use crate::machine::runtime::{convert_constr_to_tag, ANY_TAG}; + use super::script_context::{ScriptContext, ScriptPurpose, TimeRange, TxInInfo, TxInfo, TxOut}; fn wrap_with_constr(index: u64, data: PlutusData) -> PlutusData { + let converted = convert_constr_to_tag(index); PlutusData::Constr(Constr { - tag: constr_index(index), - any_constructor: None, + tag: converted.unwrap_or(ANY_TAG), + any_constructor: converted.map_or(Some(index), |_| None), fields: vec![data], }) } fn wrap_multiple_with_constr(index: u64, data: Vec) -> PlutusData { + let converted = convert_constr_to_tag(index); PlutusData::Constr(Constr { - tag: constr_index(index), - any_constructor: None, + tag: converted.unwrap_or(ANY_TAG), + any_constructor: converted.map_or(Some(index), |_| None), fields: data, }) } fn empty_constr(index: u64) -> PlutusData { + let converted = convert_constr_to_tag(index); PlutusData::Constr(Constr { - tag: constr_index(index), - any_constructor: None, + tag: converted.unwrap_or(ANY_TAG), + any_constructor: converted.map_or(Some(index), |_| None), fields: vec![], }) } -/// Translate constructor index to cbor tag. -fn constr_index(index: u64) -> u64 { - 121 + index -} - pub trait ToPlutusData { fn to_plutus_data(&self) -> PlutusData; }