Remove now-unnecessary blueprint generics.
These were needed before as a way to _partially deserialize_ blueprints. Indeed, some commands required accessing information of the blueprint, but not necessarily the schema. So out of laziness (or cleverness?), we only deserialized validators as serde::Value and achieved that through the use of generics. Now that validators and schemas have proper deserialisers, we can simply deserialize a blueprint. TODO: Our serialisation/deserialisation is safe with regards to itself; i.e. it roundtrips. However, we only supports a subset of the specified blueprint format. For example, we would fail to deserialize blueprints that have inline data-schemas (we only use references).
This commit is contained in:
parent
f0d2d20a4c
commit
cdc7ebf9a0
|
@ -5,18 +5,18 @@ pub mod validator;
|
||||||
|
|
||||||
use crate::{config::Config, module::CheckedModules};
|
use crate::{config::Config, module::CheckedModules};
|
||||||
use aiken_lang::gen_uplc::CodeGenerator;
|
use aiken_lang::gen_uplc::CodeGenerator;
|
||||||
use definitions::{Definitions, Reference};
|
use definitions::Definitions;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use schema::{Annotated, Schema};
|
use schema::{Annotated, Schema};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use validator::Validator;
|
use validator::Validator;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Blueprint<R: Default, S: Default> {
|
pub struct Blueprint {
|
||||||
pub preamble: Preamble,
|
pub preamble: Preamble,
|
||||||
pub validators: Vec<Validator<R, S>>,
|
pub validators: Vec<Validator>,
|
||||||
#[serde(skip_serializing_if = "Definitions::is_empty", default)]
|
#[serde(skip_serializing_if = "Definitions::is_empty", default)]
|
||||||
pub definitions: Definitions<S>,
|
pub definitions: Definitions<Annotated<Schema>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
@ -48,7 +48,7 @@ pub enum LookupResult<'a, T> {
|
||||||
Many,
|
Many,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blueprint<Reference, Annotated<Schema>> {
|
impl Blueprint {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
modules: &CheckedModules,
|
modules: &CheckedModules,
|
||||||
|
@ -82,12 +82,8 @@ impl Blueprint<Reference, Annotated<Schema>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R, S> Blueprint<R, S>
|
impl Blueprint {
|
||||||
where
|
pub fn lookup(&self, title: Option<&String>) -> Option<LookupResult<Validator>> {
|
||||||
R: Clone + Default,
|
|
||||||
S: Clone + Default,
|
|
||||||
{
|
|
||||||
pub fn lookup(&self, title: Option<&String>) -> Option<LookupResult<Validator<R, S>>> {
|
|
||||||
let mut validator = None;
|
let mut validator = None;
|
||||||
|
|
||||||
for v in self.validators.iter() {
|
for v in self.validators.iter() {
|
||||||
|
@ -112,7 +108,7 @@ where
|
||||||
action: F,
|
action: F,
|
||||||
) -> Result<A, E>
|
) -> Result<A, E>
|
||||||
where
|
where
|
||||||
F: Fn(Validator<R, S>) -> Result<A, E>,
|
F: Fn(Validator) -> Result<A, E>,
|
||||||
{
|
{
|
||||||
match self.lookup(title) {
|
match self.lookup(title) {
|
||||||
Some(LookupResult::One(validator)) => action(validator.to_owned()),
|
Some(LookupResult::One(validator)) => action(validator.to_owned()),
|
||||||
|
@ -152,7 +148,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_no_description() {
|
fn serialize_no_description() {
|
||||||
let blueprint: Blueprint<Reference, Annotated<Schema>> = Blueprint {
|
let blueprint = Blueprint {
|
||||||
preamble: Preamble {
|
preamble: Preamble {
|
||||||
title: "Foo".to_string(),
|
title: "Foo".to_string(),
|
||||||
description: None,
|
description: None,
|
||||||
|
@ -179,7 +175,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serialize_with_description() {
|
fn serialize_with_description() {
|
||||||
let blueprint: Blueprint<Reference, Annotated<Schema>> = Blueprint {
|
let blueprint = Blueprint {
|
||||||
preamble: Preamble {
|
preamble: Preamble {
|
||||||
title: "Foo".to_string(),
|
title: "Foo".to_string(),
|
||||||
description: Some("Lorem ipsum".to_string()),
|
description: Some("Lorem ipsum".to_string()),
|
||||||
|
@ -227,7 +223,7 @@ mod test {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let blueprint: Blueprint<Reference, Annotated<Schema>> = Blueprint {
|
let blueprint = Blueprint {
|
||||||
preamble: Preamble {
|
preamble: Preamble {
|
||||||
title: "Foo".to_string(),
|
title: "Foo".to_string(),
|
||||||
description: None,
|
description: None,
|
||||||
|
|
|
@ -13,44 +13,44 @@ use serde;
|
||||||
use uplc::ast::{DeBruijn, Program, Term};
|
use uplc::ast::{DeBruijn, Program, Term};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Validator<R, S> {
|
pub struct Validator {
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub datum: Option<Argument<R>>,
|
pub datum: Option<Argument>,
|
||||||
|
|
||||||
pub redeemer: Argument<R>,
|
pub redeemer: Argument,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub parameters: Vec<Argument<R>>,
|
pub parameters: Vec<Argument>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub program: Program<DeBruijn>,
|
pub program: Program<DeBruijn>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Definitions::is_empty")]
|
#[serde(skip_serializing_if = "Definitions::is_empty")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub definitions: Definitions<S>,
|
pub definitions: Definitions<Annotated<Schema>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Argument<T> {
|
pub struct Argument {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub title: Option<String>,
|
pub title: Option<String>,
|
||||||
|
|
||||||
pub schema: T,
|
pub schema: Reference,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Validator<Reference, Annotated<Schema>> {
|
impl Validator {
|
||||||
pub fn from_checked_module(
|
pub fn from_checked_module(
|
||||||
modules: &CheckedModules,
|
modules: &CheckedModules,
|
||||||
generator: &mut CodeGenerator,
|
generator: &mut CodeGenerator,
|
||||||
module: &CheckedModule,
|
module: &CheckedModule,
|
||||||
def: &TypedValidator,
|
def: &TypedValidator,
|
||||||
) -> Vec<Result<Validator<Reference, Annotated<Schema>>, Error>> {
|
) -> Vec<Result<Validator, Error>> {
|
||||||
let program = generator.generate(def).try_into().unwrap();
|
let program = generator.generate(def).try_into().unwrap();
|
||||||
|
|
||||||
let is_multi_validator = def.other_fun.is_some();
|
let is_multi_validator = def.other_fun.is_some();
|
||||||
|
@ -85,7 +85,7 @@ impl Validator<Reference, Annotated<Schema>> {
|
||||||
params: &[TypedArg],
|
params: &[TypedArg],
|
||||||
func: &TypedFunction,
|
func: &TypedFunction,
|
||||||
is_multi_validator: bool,
|
is_multi_validator: bool,
|
||||||
) -> Result<Validator<Reference, Annotated<Schema>>, Error> {
|
) -> Result<Validator, Error> {
|
||||||
let mut args = func.arguments.iter().rev();
|
let mut args = func.arguments.iter().rev();
|
||||||
let (_, redeemer, datum) = (args.next(), args.next().unwrap(), args.next());
|
let (_, redeemer, datum) = (args.next(), args.next().unwrap(), args.next());
|
||||||
|
|
||||||
|
@ -160,11 +160,7 @@ impl Validator<Reference, Annotated<Schema>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R, S> Validator<R, S>
|
impl Validator {
|
||||||
where
|
|
||||||
S: Clone,
|
|
||||||
R: Clone,
|
|
||||||
{
|
|
||||||
pub fn apply(self, arg: &Term<DeBruijn>) -> Result<Self, Error> {
|
pub fn apply(self, arg: &Term<DeBruijn>) -> Result<Self, Error> {
|
||||||
match self.parameters.split_first() {
|
match self.parameters.split_first() {
|
||||||
None => Err(Error::NoParametersToApply),
|
None => Err(Error::NoParametersToApply),
|
||||||
|
|
|
@ -12,11 +12,7 @@ pub mod pretty;
|
||||||
pub mod script;
|
pub mod script;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
|
|
||||||
use crate::blueprint::{
|
use crate::blueprint::Blueprint;
|
||||||
definitions::Reference,
|
|
||||||
schema::{Annotated, Schema},
|
|
||||||
Blueprint,
|
|
||||||
};
|
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{Definition, Function, ModuleKind, Tracing, TypedDataType, TypedFunction},
|
ast::{Definition, Function, ModuleKind, Tracing, TypedDataType, TypedFunction},
|
||||||
builtins,
|
builtins,
|
||||||
|
@ -218,10 +214,7 @@ where
|
||||||
self.compile(options)
|
self.compile(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_uplc(
|
pub fn dump_uplc(&self, blueprint: &Blueprint) -> Result<(), Error> {
|
||||||
&self,
|
|
||||||
blueprint: &Blueprint<Reference, Annotated<Schema>>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
let dir = self.root.join("artifacts");
|
let dir = self.root.join("artifacts");
|
||||||
|
|
||||||
self.event_listener
|
self.event_listener
|
||||||
|
@ -362,8 +355,7 @@ where
|
||||||
// Read blueprint
|
// Read blueprint
|
||||||
let blueprint = File::open(self.blueprint_path())
|
let blueprint = File::open(self.blueprint_path())
|
||||||
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
||||||
let blueprint: Blueprint<serde_json::Value, serde_json::Value> =
|
let blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;
|
||||||
serde_json::from_reader(BufReader::new(blueprint))?;
|
|
||||||
|
|
||||||
// Calculate the address
|
// Calculate the address
|
||||||
let when_too_many =
|
let when_too_many =
|
||||||
|
@ -386,12 +378,11 @@ where
|
||||||
&self,
|
&self,
|
||||||
title: Option<&String>,
|
title: Option<&String>,
|
||||||
param: &Term<DeBruijn>,
|
param: &Term<DeBruijn>,
|
||||||
) -> Result<Blueprint<serde_json::Value, serde_json::Value>, Error> {
|
) -> Result<Blueprint, Error> {
|
||||||
// Read blueprint
|
// Read blueprint
|
||||||
let blueprint = File::open(self.blueprint_path())
|
let blueprint = File::open(self.blueprint_path())
|
||||||
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
.map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?;
|
||||||
let mut blueprint: Blueprint<serde_json::Value, serde_json::Value> =
|
let mut blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?;
|
||||||
serde_json::from_reader(BufReader::new(blueprint))?;
|
|
||||||
|
|
||||||
// Apply parameters
|
// Apply parameters
|
||||||
let when_too_many =
|
let when_too_many =
|
||||||
|
|
|
@ -65,7 +65,7 @@ pub fn exec(
|
||||||
.map_err(|_| BlueprintError::InvalidOrMissingFile)
|
.map_err(|_| BlueprintError::InvalidOrMissingFile)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
|
|
||||||
let blueprint: Blueprint<serde_json::Value, serde_json::Value> =
|
let blueprint: Blueprint =
|
||||||
serde_json::from_reader(BufReader::new(blueprint)).into_diagnostic()?;
|
serde_json::from_reader(BufReader::new(blueprint)).into_diagnostic()?;
|
||||||
|
|
||||||
// Perform the conversion
|
// Perform the conversion
|
||||||
|
|
Loading…
Reference in New Issue