Merge pull request #347 from spacebudz/constr

Fix constructor tag range
This commit is contained in:
Ales 2023-02-08 14:52:50 +01:00 committed by GitHub
commit 242eaa8b67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 49 deletions

View File

@ -8,7 +8,7 @@ use uplc::{
Constant as UplcConstant, Name, Term, Type as UplcType, Constant as UplcConstant, Name, Term, Type as UplcType,
}, },
builtins::DefaultFunction, builtins::DefaultFunction,
machine::runtime::convert_constr_to_tag, machine::runtime::{convert_constr_to_tag, ANY_TAG},
BigInt, Constr, KeyValuePairs, PlutusData, BigInt, Constr, KeyValuePairs, PlutusData,
}; };
@ -237,7 +237,7 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
term, term,
Term::Constant( Term::Constant(
UplcConstant::Data(PlutusData::Constr(Constr { UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(1), tag: convert_constr_to_tag(1).unwrap(),
any_constructor: None, any_constructor: None,
fields: vec![], fields: vec![],
})) }))
@ -245,7 +245,7 @@ pub fn convert_type_to_data(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
), ),
Term::Constant( Term::Constant(
UplcConstant::Data(PlutusData::Constr(Constr { UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag(0), tag: convert_constr_to_tag(0).unwrap(),
any_constructor: None, any_constructor: None,
fields: vec![], fields: vec![],
})) }))
@ -1002,8 +1002,9 @@ pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcCo
)), )),
UplcConstant::Bool(b) => UplcConstant::Data(PlutusData::Constr(Constr { UplcConstant::Bool(b) => UplcConstant::Data(PlutusData::Constr(Constr {
tag: convert_constr_to_tag((*b).into()), tag: convert_constr_to_tag((*b).into()).unwrap_or(ANY_TAG),
any_constructor: None, any_constructor: convert_constr_to_tag((*b).into())
.map_or(Some((*b).into()), |_| None),
fields: vec![], fields: vec![],
})), })),
UplcConstant::ProtoList(_, constants) => { UplcConstant::ProtoList(_, constants) => {

View File

@ -880,9 +880,9 @@ impl DefaultFunction {
.collect(); .collect();
let constr_data = PlutusData::Constr(Constr { let constr_data = PlutusData::Constr(Constr {
// TODO: handle other types of constructor tags tag: convert_constr_to_tag(*i as u64).unwrap_or(ANY_TAG),
tag: convert_constr_to_tag(*i as u64), any_constructor: convert_constr_to_tag(*i as u64)
any_constructor: None, .map_or(Some(*i as u64), |_| None),
fields: data_list, fields: data_list,
}); });
@ -959,27 +959,29 @@ impl DefaultFunction {
}, },
DefaultFunction::UnConstrData => match args[0].as_ref() { DefaultFunction::UnConstrData => match args[0].as_ref() {
Value::Con(con) => match con.as_ref() { Value::Con(con) => match con.as_ref() {
Constant::Data(PlutusData::Constr(c)) => { Constant::Data(PlutusData::Constr(c)) => Ok(Value::Con(
Ok(Value::Con( Constant::ProtoPair(
Constant::ProtoPair( Type::Integer,
Type::Integer, Type::List(Type::Data.into()),
Type::List(Type::Data.into()), Constant::Integer(
// TODO: handle other types of constructor tags convert_tag_to_constr(c.tag)
Constant::Integer(convert_tag_to_constr(c.tag as i128)).into(), .unwrap_or_else(|| c.any_constructor.unwrap())
Constant::ProtoList( as i128,
Type::Data, )
c.fields .into(),
.deref() Constant::ProtoList(
.iter() Type::Data,
.map(|d| Constant::Data(d.clone())) c.fields
.collect(), .deref()
) .iter()
.into(), .map(|d| Constant::Data(d.clone()))
.collect(),
) )
.into(), .into(),
) )
.into()) .into(),
} )
.into()),
v => Err(Error::DeserialisationError( v => Err(Error::DeserialisationError(
"UnConstrData".to_string(), "UnConstrData".to_string(),
Value::Con(v.clone().into()), Value::Con(v.clone().into()),
@ -1126,26 +1128,28 @@ impl DefaultFunction {
} }
} }
pub fn convert_tag_to_constr(tag: i128) -> i128 { pub fn convert_tag_to_constr(tag: u64) -> Option<u64> {
if tag < 128 { if (121..=127).contains(&tag) {
tag - 121 Some(tag - 121)
} else if (1280..1401).contains(&tag) { } else if (1280..=1400).contains(&tag) {
tag - 1280 Some(tag - 1280 + 7)
} else { } else {
todo!() None
} }
} }
pub fn convert_constr_to_tag(constr: u64) -> u64 { pub fn convert_constr_to_tag(constr: u64) -> Option<u64> {
if constr < 7 { if (0..=6).contains(&constr) {
constr + 121 Some(121 + constr)
} else if constr < 128 { } else if (7..=127).contains(&constr) {
constr + 1280 Some(1280 - 7 + constr)
} else { } else {
todo!() None // 102 otherwise
} }
} }
pub static ANY_TAG: u64 = 102;
#[cfg(not(feature = "native-secp256k1"))] #[cfg(not(feature = "native-secp256k1"))]
fn verify_ecdsa(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result<Rc<Value>, Error> { fn verify_ecdsa(public_key: &[u8], message: &[u8], signature: &[u8]) -> Result<Rc<Value>, Error> {
use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1}; use secp256k1::{ecdsa::Signature, Message, PublicKey, Secp256k1};

View File

@ -8,37 +8,37 @@ use pallas_primitives::babbage::{
}; };
use pallas_traverse::ComputeHash; use pallas_traverse::ComputeHash;
use crate::machine::runtime::{convert_constr_to_tag, ANY_TAG};
use super::script_context::{ScriptContext, ScriptPurpose, TimeRange, TxInInfo, TxInfo, TxOut}; use super::script_context::{ScriptContext, ScriptPurpose, TimeRange, TxInInfo, TxInfo, TxOut};
fn wrap_with_constr(index: u64, data: PlutusData) -> PlutusData { fn wrap_with_constr(index: u64, data: PlutusData) -> PlutusData {
let converted = convert_constr_to_tag(index);
PlutusData::Constr(Constr { PlutusData::Constr(Constr {
tag: constr_index(index), tag: converted.unwrap_or(ANY_TAG),
any_constructor: None, any_constructor: converted.map_or(Some(index), |_| None),
fields: vec![data], fields: vec![data],
}) })
} }
fn wrap_multiple_with_constr(index: u64, data: Vec<PlutusData>) -> PlutusData { fn wrap_multiple_with_constr(index: u64, data: Vec<PlutusData>) -> PlutusData {
let converted = convert_constr_to_tag(index);
PlutusData::Constr(Constr { PlutusData::Constr(Constr {
tag: constr_index(index), tag: converted.unwrap_or(ANY_TAG),
any_constructor: None, any_constructor: converted.map_or(Some(index), |_| None),
fields: data, fields: data,
}) })
} }
fn empty_constr(index: u64) -> PlutusData { fn empty_constr(index: u64) -> PlutusData {
let converted = convert_constr_to_tag(index);
PlutusData::Constr(Constr { PlutusData::Constr(Constr {
tag: constr_index(index), tag: converted.unwrap_or(ANY_TAG),
any_constructor: None, any_constructor: converted.map_or(Some(index), |_| None),
fields: vec![], fields: vec![],
}) })
} }
/// Translate constructor index to cbor tag.
fn constr_index(index: u64) -> u64 {
121 + index
}
pub trait ToPlutusData { pub trait ToPlutusData {
fn to_plutus_data(&self) -> PlutusData; fn to_plutus_data(&self) -> PlutusData;
} }