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

View File

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