Implement blueprint schema & data validations.

This commit is contained in:
KtorZ
2023-04-07 11:53:19 +02:00
parent ee220881b6
commit d58ef1a079
6 changed files with 842 additions and 118 deletions

View File

@@ -13,7 +13,6 @@ use serde::{
};
use serde_json as json;
use std::{collections::HashMap, fmt, ops::Deref, sync::Arc};
use uplc::ast::Term;
// NOTE: Can be anything BUT 0
pub const REDEEMER_DISCRIMINANT: usize = 1;
@@ -35,6 +34,43 @@ pub enum Declaration<T> {
Inline(Box<T>),
}
impl<'a, T> Declaration<T> {
pub fn reference(&'a self) -> Option<&'a Reference> {
match self {
Declaration::Referenced(reference) => Some(reference),
Declaration::Inline(..) => None,
}
}
fn try_schema(
&'a self,
definitions: &'a Definitions<Annotated<Schema>>,
cast: fn(&'a Schema) -> Option<&'a T>,
) -> Option<&'a T> {
match self {
Declaration::Inline(inner) => Some(inner.deref()),
Declaration::Referenced(reference) => definitions
.lookup(reference)
.and_then(|s| cast(&s.annotated)),
}
}
}
impl<'a> Declaration<Data> {
pub fn schema(&'a self, definitions: &'a Definitions<Annotated<Schema>>) -> Option<&'a Data> {
self.try_schema(definitions, |s| match s {
Schema::Data(data) => Some(data),
_ => None,
})
}
}
impl<'a> Declaration<Schema> {
pub fn schema(&'a self, definitions: &'a Definitions<Annotated<Schema>>) -> Option<&'a Schema> {
self.try_schema(definitions, Some)
}
}
/// A schema for low-level UPLC primitives.
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Schema {
@@ -71,7 +107,6 @@ pub enum Items<T> {
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Constructor {
pub index: usize,
// TODO: Generalize to work with either Reference or Data
pub fields: Vec<Annotated<Declaration<Data>>>,
}
@@ -85,50 +120,6 @@ impl<T> From<T> for Annotated<T> {
}
}
impl<'a, T> TryFrom<&'a Term<T>> for Schema {
type Error = &'a str;
fn try_from(term: &'a Term<T>) -> Result<Schema, Self::Error> {
use uplc::{ast::Constant, Constr, PlutusData};
match term {
Term::Constant(constant) => match constant.deref() {
Constant::Integer(..) => Ok(Schema::Integer),
Constant::Bool(..) => Ok(Schema::Boolean),
Constant::ByteString(..) => Ok(Schema::Bytes),
Constant::String(..) => Ok(Schema::String),
Constant::Unit => Ok(Schema::Unit),
Constant::ProtoList{..} => todo!("can't convert from ProtoList to Schema; note that you probably want to use a Data's list instead anyway."),
Constant::ProtoPair{..} => todo!("can't convert from ProtoPair to Schema; note that you probably want to use a Data's list instead anyway."),
Constant::Data(data) => Ok(Schema::Data(match data {
PlutusData::BigInt(..) => {
Data::Integer
}
PlutusData::BoundedBytes(..) => {
Data::Bytes
}
PlutusData::Array(elems) => {
todo!()
}
PlutusData::Map(keyValuePair) => {
todo!()
}
PlutusData::Constr(Constr{ tag, fields, any_constructor }) => {
todo!()
}
}))
},
Term::Delay(..)
| Term::Lambda { .. }
| Term::Var(..)
| Term::Apply { .. }
| Term::Force(..)
| Term::Error
| Term::Builtin(..) => Err("not a UPLC constant"),
}
}
}
impl Annotated<Schema> {
pub fn as_wrapped_redeemer(
definitions: &mut Definitions<Annotated<Schema>>,