feat: delay typemismatch errors in the machine runtime

to pass 2 of the conformance tests, we need to make sure
that we aren't typechecking builtin arguments as arguments
are applied. This switches push to by removing the call to check_type
and then reworking all the associated unwrap methods on Value
so that they return the same errors that were being returned before.
This commit is contained in:
rvcas 2023-11-16 23:55:07 -05:00 committed by Lucas
parent ed909055b5
commit 9ab458dcc6
7 changed files with 226 additions and 241 deletions

View File

@ -89,8 +89,6 @@ impl BuiltinRuntime {
}
pub fn push(&mut self, arg: Value) -> Result<(), Error> {
self.fun.check_type(&arg, &self.args)?;
self.args.push(arg);
Ok(())
@ -437,8 +435,8 @@ impl DefaultFunction {
) -> Result<Value, Error> {
match self {
DefaultFunction::AddInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let result = arg1 + arg2;
@ -447,8 +445,8 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::SubtractInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let result = arg1 - arg2;
@ -457,8 +455,8 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::MultiplyInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let result = arg1 * arg2;
@ -467,8 +465,8 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::DivideInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
if *arg2 != 0.into() {
let (result, _) = arg1.div_mod_floor(arg2);
@ -481,8 +479,8 @@ impl DefaultFunction {
}
}
DefaultFunction::QuotientInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
if *arg2 != 0.into() {
let (result, _) = arg1.div_rem(arg2);
@ -495,8 +493,8 @@ impl DefaultFunction {
}
}
DefaultFunction::RemainderInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
if *arg2 != 0.into() {
let (_, result) = arg1.div_rem(arg2);
@ -509,8 +507,8 @@ impl DefaultFunction {
}
}
DefaultFunction::ModInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
if *arg2 != 0.into() {
let (_, result) = arg1.div_mod_floor(arg2);
@ -523,32 +521,32 @@ impl DefaultFunction {
}
}
DefaultFunction::EqualsInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let value = Value::bool(arg1 == arg2);
Ok(value)
}
DefaultFunction::LessThanInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let value = Value::bool(arg1 < arg2);
Ok(value)
}
DefaultFunction::LessThanEqualsInteger => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let value = Value::bool(arg1 <= arg2);
Ok(value)
}
DefaultFunction::AppendByteString => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_byte_string()?;
let result = arg1.iter().copied().chain(arg2.iter().copied()).collect();
@ -557,8 +555,8 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::ConsByteString => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_byte_string()?;
let byte: u8 = match semantics {
BuiltinSemantics::V1 => {
@ -584,9 +582,9 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::SliceByteString => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_integer();
let arg3 = args[2].unwrap_byte_string();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_integer()?;
let arg3 = args[2].unwrap_byte_string()?;
let skip: usize = if arg1.lt(&0.into()) {
0
@ -606,15 +604,15 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::LengthOfByteString => {
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let value = Value::integer(arg1.len().into());
Ok(value)
}
DefaultFunction::IndexByteString => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_integer();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_integer()?;
let index: i128 = arg2.try_into().unwrap();
@ -629,24 +627,24 @@ impl DefaultFunction {
}
}
DefaultFunction::EqualsByteString => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_byte_string()?;
let value = Value::bool(arg1 == arg2);
Ok(value)
}
DefaultFunction::LessThanByteString => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_byte_string()?;
let value = Value::bool(arg1 < arg2);
Ok(value)
}
DefaultFunction::LessThanEqualsByteString => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_byte_string()?;
let value = Value::bool(arg1 <= arg2);
@ -655,7 +653,7 @@ impl DefaultFunction {
DefaultFunction::Sha2_256 => {
use cryptoxide::{digest::Digest, sha2::Sha256};
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let mut hasher = Sha256::new();
@ -672,7 +670,7 @@ impl DefaultFunction {
DefaultFunction::Sha3_256 => {
use cryptoxide::{digest::Digest, sha3::Sha3_256};
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let mut hasher = Sha3_256::new();
@ -690,7 +688,7 @@ impl DefaultFunction {
DefaultFunction::Blake2b_224 => {
use cryptoxide::{blake2b::Blake2b, digest::Digest};
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let mut digest = [0u8; 28];
let mut context = Blake2b::new(28);
@ -705,7 +703,7 @@ impl DefaultFunction {
DefaultFunction::Blake2b_256 => {
use cryptoxide::{blake2b::Blake2b, digest::Digest};
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let mut digest = [0u8; 32];
let mut context = Blake2b::new(32);
@ -720,7 +718,7 @@ impl DefaultFunction {
DefaultFunction::Keccak_256 => {
use cryptoxide::{digest::Digest, sha3::Keccak256};
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let mut hasher = Keccak256::new();
@ -737,9 +735,9 @@ impl DefaultFunction {
DefaultFunction::VerifyEd25519Signature => {
use cryptoxide::ed25519;
let public_key = args[0].unwrap_byte_string();
let message = args[1].unwrap_byte_string();
let signature = args[2].unwrap_byte_string();
let public_key = args[0].unwrap_byte_string()?;
let message = args[1].unwrap_byte_string()?;
let signature = args[2].unwrap_byte_string()?;
let public_key: [u8; 32] = public_key
.clone()
@ -758,37 +756,37 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::VerifyEcdsaSecp256k1Signature => {
let public_key = args[0].unwrap_byte_string();
let message = args[1].unwrap_byte_string();
let signature = args[2].unwrap_byte_string();
let public_key = args[0].unwrap_byte_string()?;
let message = args[1].unwrap_byte_string()?;
let signature = args[2].unwrap_byte_string()?;
verify_ecdsa(public_key, message, signature)
}
DefaultFunction::VerifySchnorrSecp256k1Signature => {
let public_key = args[0].unwrap_byte_string();
let message = args[1].unwrap_byte_string();
let signature = args[2].unwrap_byte_string();
let public_key = args[0].unwrap_byte_string()?;
let message = args[1].unwrap_byte_string()?;
let signature = args[2].unwrap_byte_string()?;
verify_schnorr(public_key, message, signature)
}
DefaultFunction::AppendString => {
let arg1 = args[0].unwrap_string();
let arg2 = args[1].unwrap_string();
let arg1 = args[0].unwrap_string()?;
let arg2 = args[1].unwrap_string()?;
let value = Value::string(format!("{arg1}{arg2}"));
Ok(value)
}
DefaultFunction::EqualsString => {
let arg1 = args[0].unwrap_string();
let arg2 = args[1].unwrap_string();
let arg1 = args[0].unwrap_string()?;
let arg2 = args[1].unwrap_string()?;
let value = Value::bool(arg1 == arg2);
Ok(value)
}
DefaultFunction::EncodeUtf8 => {
let arg1 = args[0].unwrap_string();
let arg1 = args[0].unwrap_string()?;
let bytes = arg1.as_bytes().to_vec();
@ -797,7 +795,7 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::DecodeUtf8 => {
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let string = String::from_utf8(arg1.clone())?;
@ -806,7 +804,7 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::IfThenElse => {
let condition = args[0].unwrap_bool();
let condition = args[0].unwrap_bool()?;
if *condition {
Ok(args[1].clone())
@ -815,35 +813,33 @@ impl DefaultFunction {
}
}
DefaultFunction::ChooseUnit => {
// We don't need to check it here because this is already done in
// expect_type
// let Value::Con(Constant::Unit) = args[0] else {unreachable!()};
args[0].unwrap_unit()?;
Ok(args[1].clone())
}
DefaultFunction::Trace => {
let arg1 = args[0].unwrap_string();
let arg1 = args[0].unwrap_string()?;
logs.push(arg1.clone());
Ok(args[1].clone())
}
DefaultFunction::FstPair => {
let (_, _, first, _) = args[0].unwrap_pair();
let (_, _, first, _) = args[0].unwrap_pair()?;
let value = Value::Con(first.clone());
Ok(value)
}
DefaultFunction::SndPair => {
let (_, _, _, second) = args[0].unwrap_pair();
let (_, _, _, second) = args[0].unwrap_pair()?;
let value = Value::Con(second.clone());
Ok(value)
}
DefaultFunction::ChooseList => {
let (_, list) = args[0].unwrap_list();
let (_, list) = args[0].unwrap_list()?;
if list.is_empty() {
Ok(args[1].clone())
@ -852,8 +848,12 @@ impl DefaultFunction {
}
}
DefaultFunction::MkCons => {
let item = args[0].unwrap_constant();
let (r#type, list) = args[1].unwrap_list();
let item = args[0].unwrap_constant()?;
let (r#type, list) = args[1].unwrap_list()?;
if *r#type != Type::from(item) {
return Err(Error::TypeMismatch(Type::from(item), r#type.clone()));
}
let mut ret = vec![item.clone()];
@ -864,15 +864,10 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::HeadList => {
let c @ Value::Con(inner) = &args[0] else {
unreachable!()
};
let Constant::ProtoList(_, list) = inner.as_ref() else {
unreachable!()
};
let (_, list) = args[0].unwrap_list()?;
if list.is_empty() {
Err(Error::EmptyList(c.clone()))
Err(Error::EmptyList(args[0].clone()))
} else {
let value = Value::Con(list[0].clone().into());
@ -880,15 +875,10 @@ impl DefaultFunction {
}
}
DefaultFunction::TailList => {
let c @ Value::Con(inner) = &args[0] else {
unreachable!()
};
let Constant::ProtoList(r#type, list) = inner.as_ref() else {
unreachable!()
};
let (r#type, list) = args[0].unwrap_list()?;
if list.is_empty() {
Err(Error::EmptyList(c.clone()))
Err(Error::EmptyList(args[0].clone()))
} else {
let value = Value::list(r#type.clone(), list[1..].to_vec());
@ -896,14 +886,14 @@ impl DefaultFunction {
}
}
DefaultFunction::NullList => {
let (_, list) = args[0].unwrap_list();
let (_, list) = args[0].unwrap_list()?;
let value = Value::bool(list.is_empty());
Ok(value)
}
DefaultFunction::ChooseData => {
let con = args[0].unwrap_constant();
let con = args[0].unwrap_constant()?;
match con {
Constant::Data(PlutusData::Constr(_)) => Ok(args[1].clone()),
@ -915,8 +905,8 @@ impl DefaultFunction {
}
}
DefaultFunction::ConstrData => {
let i = args[0].unwrap_integer();
let l = args[1].unwrap_data_list();
let i = args[0].unwrap_integer()?;
let l = args[1].unwrap_data_list()?;
let data_list: Vec<PlutusData> = l
.iter()
@ -939,7 +929,7 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::MapData => {
let (_, list) = args[0].unwrap_list();
let (_, list) = args[0].unwrap_list()?;
let mut map = Vec::new();
@ -961,7 +951,7 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::ListData => {
let (_, list) = args[0].unwrap_list();
let (_, list) = args[0].unwrap_list()?;
let data_list: Vec<PlutusData> = list
.iter()
@ -976,14 +966,14 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::IData => {
let i = args[0].unwrap_integer();
let i = args[0].unwrap_integer()?;
let value = Value::data(PlutusData::BigInt(to_pallas_bigint(i)));
Ok(value)
}
DefaultFunction::BData => {
let b = args[0].unwrap_byte_string();
let b = args[0].unwrap_byte_string()?;
let value = Value::data(PlutusData::BoundedBytes(b.clone().try_into().unwrap()));
@ -1022,10 +1012,7 @@ impl DefaultFunction {
Ok(value)
}
v => Err(Error::DeserialisationError(
"UnConstrData".to_string(),
v.clone(),
)),
v => Err(Error::NotAConstant(v.clone())),
},
DefaultFunction::UnMapData => match &args[0] {
v @ Value::Con(inner) => {
@ -1055,10 +1042,7 @@ impl DefaultFunction {
Ok(value)
}
v => Err(Error::DeserialisationError(
"UnMapData".to_string(),
v.clone(),
)),
v => Err(Error::NotAConstant(v.clone())),
},
DefaultFunction::UnListData => match &args[0] {
v @ Value::Con(inner) => {
@ -1079,10 +1063,7 @@ impl DefaultFunction {
Ok(value)
}
v => Err(Error::DeserialisationError(
"UnListData".to_string(),
v.clone(),
)),
v => Err(Error::NotAConstant(v.clone())),
},
DefaultFunction::UnIData => match &args[0] {
v @ Value::Con(inner) => {
@ -1097,10 +1078,7 @@ impl DefaultFunction {
Ok(value)
}
v => Err(Error::DeserialisationError(
"UnIData".to_string(),
v.clone(),
)),
v => Err(Error::NotAConstant(v.clone())),
},
DefaultFunction::UnBData => match &args[0] {
v @ Value::Con(inner) => {
@ -1115,34 +1093,18 @@ impl DefaultFunction {
Ok(value)
}
v => Err(Error::DeserialisationError(
"UnBData".to_string(),
v.clone(),
)),
v => Err(Error::NotAConstant(v.clone())),
},
DefaultFunction::EqualsData => {
let (Value::Con(inner1), Value::Con(inner2)) = (&args[0], &args[1]) else {
unreachable!()
};
let Constant::Data(d1) = inner1.as_ref() else {
unreachable!()
};
let Constant::Data(d2) = inner2.as_ref() else {
unreachable!()
};
let d1 = args[0].unwrap_data()?;
let d2 = args[1].unwrap_data()?;
let value = Value::bool(d1.eq(d2));
Ok(value)
}
DefaultFunction::SerialiseData => {
let Value::Con(inner) = &args[0] else {
unreachable!()
};
let Constant::Data(d) = inner.as_ref() else {
unreachable!()
};
let d = args[0].unwrap_data()?;
let serialized_data = plutus_data_to_bytes(d).unwrap();
@ -1151,16 +1113,8 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::MkPairData => {
let (Value::Con(inner1), Value::Con(inner2)) = (&args[0], &args[1]) else {
unreachable!()
};
let Constant::Data(d1) = inner1.as_ref() else {
unreachable!()
};
let Constant::Data(d2) = inner2.as_ref() else {
unreachable!()
};
let d1 = args[0].unwrap_data()?;
let d2 = args[1].unwrap_data()?;
let constant = Constant::ProtoPair(
Type::Data,
@ -1174,11 +1128,15 @@ impl DefaultFunction {
Ok(value)
}
DefaultFunction::MkNilData => {
args[0].unwrap_unit()?;
let value = Value::list(Type::Data, vec![]);
Ok(value)
}
DefaultFunction::MkNilPairData => {
args[0].unwrap_unit()?;
let constant = Constant::ProtoList(
Type::Pair(Rc::new(Type::Data), Rc::new(Type::Data)),
vec![],
@ -1190,8 +1148,8 @@ impl DefaultFunction {
}
DefaultFunction::Bls12_381_G1_Add => {
let arg1 = args[0].unwrap_bls12_381_g1_element();
let arg2 = args[1].unwrap_bls12_381_g1_element();
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
let arg2 = args[1].unwrap_bls12_381_g1_element()?;
let mut out = blst::blst_p1::default();
@ -1208,7 +1166,7 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G1_Neg => {
let arg1 = args[0].unwrap_bls12_381_g1_element();
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
let mut out = *arg1;
@ -1225,8 +1183,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G1_ScalarMul => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_bls12_381_g1_element();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_bls12_381_g1_element()?;
let size_scalar = size_of::<blst::blst_scalar>();
@ -1266,8 +1224,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G1_Equal => {
let arg1 = args[0].unwrap_bls12_381_g1_element();
let arg2 = args[1].unwrap_bls12_381_g1_element();
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
let arg2 = args[1].unwrap_bls12_381_g1_element()?;
let is_equal = unsafe { blst::blst_p1_is_equal(arg1, arg2) };
@ -1276,7 +1234,7 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G1_Compress => {
let arg1 = args[0].unwrap_bls12_381_g1_element();
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
let out = arg1.compress();
@ -1285,7 +1243,7 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G1_Uncompress => {
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let out = blst::blst_p1::uncompress(arg1)?;
@ -1294,8 +1252,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G1_HashToGroup => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_byte_string()?;
if arg2.len() > 255 {
return Err(Error::HashToCurveDstTooBig);
@ -1321,8 +1279,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_Add => {
let arg1 = args[0].unwrap_bls12_381_g2_element();
let arg2 = args[1].unwrap_bls12_381_g2_element();
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
let mut out = blst::blst_p2::default();
@ -1339,7 +1297,7 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_Neg => {
let arg1 = args[0].unwrap_bls12_381_g2_element();
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
let mut out = *arg1;
@ -1356,8 +1314,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_ScalarMul => {
let arg1 = args[0].unwrap_integer();
let arg2 = args[1].unwrap_bls12_381_g2_element();
let arg1 = args[0].unwrap_integer()?;
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
let size_scalar = size_of::<blst::blst_scalar>();
@ -1397,8 +1355,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_Equal => {
let arg1 = args[0].unwrap_bls12_381_g2_element();
let arg2 = args[1].unwrap_bls12_381_g2_element();
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
let is_equal = unsafe { blst::blst_p2_is_equal(arg1, arg2) };
@ -1407,7 +1365,7 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_Compress => {
let arg1 = args[0].unwrap_bls12_381_g2_element();
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
let out = arg1.compress();
@ -1416,7 +1374,7 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_Uncompress => {
let arg1 = args[0].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let out = blst::blst_p2::uncompress(arg1)?;
@ -1425,8 +1383,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_G2_HashToGroup => {
let arg1 = args[0].unwrap_byte_string();
let arg2 = args[1].unwrap_byte_string();
let arg1 = args[0].unwrap_byte_string()?;
let arg2 = args[1].unwrap_byte_string()?;
if arg2.len() > 255 {
return Err(Error::HashToCurveDstTooBig);
@ -1452,8 +1410,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_MillerLoop => {
let arg1 = args[0].unwrap_bls12_381_g1_element();
let arg2 = args[1].unwrap_bls12_381_g2_element();
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
let mut out = blst::blst_fp12::default();
@ -1472,8 +1430,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_MulMlResult => {
let arg1 = args[0].unwrap_bls12_381_ml_result();
let arg2 = args[1].unwrap_bls12_381_ml_result();
let arg1 = args[0].unwrap_bls12_381_ml_result()?;
let arg2 = args[1].unwrap_bls12_381_ml_result()?;
let mut out = blst::blst_fp12::default();
@ -1486,8 +1444,8 @@ impl DefaultFunction {
Ok(Value::Con(constant.into()))
}
DefaultFunction::Bls12_381_FinalVerify => {
let arg1 = args[0].unwrap_bls12_381_ml_result();
let arg2 = args[1].unwrap_bls12_381_ml_result();
let arg1 = args[0].unwrap_bls12_381_ml_result()?;
let arg2 = args[1].unwrap_bls12_381_ml_result()?;
let verified = unsafe { blst::blst_fp12_finalverify(arg1, arg2) };

View File

@ -69,125 +69,138 @@ impl Value {
Value::Con(constant.into())
}
pub(super) fn unwrap_integer(&self) -> &BigInt {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::Integer(integer) = inner.as_ref() else {
unreachable!()
pub(super) fn unwrap_integer(&self) -> Result<&BigInt, Error> {
let inner = self.unwrap_constant()?;
let Constant::Integer(integer) = inner else {
return Err(Error::TypeMismatch(Type::Integer, inner.into()));
};
integer
Ok(integer)
}
pub(super) fn unwrap_byte_string(&self) -> &Vec<u8> {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::ByteString(byte_string) = inner.as_ref() else {
unreachable!()
pub(super) fn unwrap_byte_string(&self) -> Result<&Vec<u8>, Error> {
let inner = self.unwrap_constant()?;
let Constant::ByteString(byte_string) = inner else {
return Err(Error::TypeMismatch(Type::ByteString, inner.into()));
};
byte_string
Ok(byte_string)
}
pub(super) fn unwrap_string(&self) -> &String {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::String(string) = inner.as_ref() else {
unreachable!()
pub(super) fn unwrap_string(&self) -> Result<&String, Error> {
let inner = self.unwrap_constant()?;
let Constant::String(string) = inner else {
return Err(Error::TypeMismatch(Type::String, inner.into()));
};
string
Ok(string)
}
pub(super) fn unwrap_bool(&self) -> &bool {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::Bool(condition) = inner.as_ref() else {
unreachable!()
pub(super) fn unwrap_bool(&self) -> Result<&bool, Error> {
let inner = self.unwrap_constant()?;
let Constant::Bool(condition) = inner else {
return Err(Error::TypeMismatch(Type::Bool, inner.into()));
};
condition
Ok(condition)
}
pub(super) fn unwrap_pair(&self) -> (&Type, &Type, &Rc<Constant>, &Rc<Constant>) {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::ProtoPair(t1, t2, first, second) = inner.as_ref() else {
unreachable!()
#[allow(clippy::type_complexity)]
pub(super) fn unwrap_pair(
&self,
) -> Result<(&Type, &Type, &Rc<Constant>, &Rc<Constant>), Error> {
let inner = self.unwrap_constant()?;
let Constant::ProtoPair(t1, t2, first, second) = inner else {
return Err(Error::PairTypeMismatch(inner.into()));
};
(t1, t2, first, second)
Ok((t1, t2, first, second))
}
pub(super) fn unwrap_list(&self) -> (&Type, &Vec<Constant>) {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::ProtoList(t, list) = inner.as_ref() else {
unreachable!()
pub(super) fn unwrap_list(&self) -> Result<(&Type, &Vec<Constant>), Error> {
let inner = self.unwrap_constant()?;
let Constant::ProtoList(t, list) = inner else {
return Err(Error::ListTypeMismatch(inner.into()));
};
(t, list)
Ok((t, list))
}
pub(super) fn unwrap_constant(&self) -> &Constant {
pub(super) fn unwrap_data(&self) -> Result<&PlutusData, Error> {
let inner = self.unwrap_constant()?;
let Constant::Data(data) = inner else {
return Err(Error::TypeMismatch(Type::Data, inner.into()));
};
Ok(data)
}
pub(super) fn unwrap_unit(&self) -> Result<(), Error> {
let inner = self.unwrap_constant()?;
let Constant::Unit = inner else {
return Err(Error::TypeMismatch(Type::Unit, inner.into()));
};
Ok(())
}
pub(super) fn unwrap_constant(&self) -> Result<&Constant, Error> {
let Value::Con(item) = self else {
unreachable!()
return Err(Error::NotAConstant(self.clone()));
};
item.as_ref()
Ok(item.as_ref())
}
pub(super) fn unwrap_data_list(&self) -> &Vec<Constant> {
let Value::Con(inner) = self else {
unreachable!()
};
let Constant::ProtoList(Type::Data, list) = inner.as_ref() else {
unreachable!()
pub(super) fn unwrap_data_list(&self) -> Result<&Vec<Constant>, Error> {
let inner = self.unwrap_constant()?;
let Constant::ProtoList(Type::Data, list) = inner else {
return Err(Error::TypeMismatch(
Type::List(Type::Data.into()),
inner.into(),
));
};
list
Ok(list)
}
pub(super) fn unwrap_bls12_381_g1_element(&self) -> &blst::blst_p1 {
let Value::Con(inner) = self else {
unreachable!()
pub(super) fn unwrap_bls12_381_g1_element(&self) -> Result<&blst::blst_p1, Error> {
let inner = self.unwrap_constant()?;
let Constant::Bls12_381G1Element(element) = inner else {
return Err(Error::TypeMismatch(Type::Bls12_381G1Element, inner.into()));
};
let Constant::Bls12_381G1Element(element) = inner.as_ref() else {
unreachable!()
};
element
Ok(element)
}
pub(super) fn unwrap_bls12_381_g2_element(&self) -> &blst::blst_p2 {
let Value::Con(inner) = self else {
unreachable!()
pub(super) fn unwrap_bls12_381_g2_element(&self) -> Result<&blst::blst_p2, Error> {
let inner = self.unwrap_constant()?;
let Constant::Bls12_381G2Element(element) = inner else {
return Err(Error::TypeMismatch(Type::Bls12_381G2Element, inner.into()));
};
let Constant::Bls12_381G2Element(element) = inner.as_ref() else {
unreachable!()
};
element
Ok(element)
}
pub(super) fn unwrap_bls12_381_ml_result(&self) -> &blst::blst_fp12 {
let Value::Con(inner) = self else {
unreachable!()
pub(super) fn unwrap_bls12_381_ml_result(&self) -> Result<&blst::blst_fp12, Error> {
let inner = self.unwrap_constant()?;
let Constant::Bls12_381MlResult(element) = inner else {
return Err(Error::TypeMismatch(Type::Bls12_381MlResult, inner.into()));
};
let Constant::Bls12_381MlResult(element) = inner.as_ref() else {
unreachable!()
};
element
Ok(element)
}
pub fn is_integer(&self) -> bool {

View File

@ -0,0 +1,7 @@
(program
1.0.0
[
[ (force (builtin ifThenElse)) (con string "11 <= 22") ]
(con string "\172(11 <= 22)")
]
)

View File

@ -0,0 +1,4 @@
(program 1.0.0 [
[ (force (builtin ifThenElse)) (con string "11 <= 22") ]
(con string "\172(11 <= 22)")
])

View File

@ -0,0 +1,2 @@
-- ill-typed but does not fail at runtime because the builtin application is not saturated.
(program 1.0.0 [(builtin addInteger) (con unit ())])

View File

@ -0,0 +1 @@
(program 1.0.0 [ (builtin addInteger) (con unit ()) ])