From 961e323c3669836ff3194272e58afebdc98edfeb Mon Sep 17 00:00:00 2001 From: KtorZ Date: Sat, 19 Aug 2023 16:38:44 +0200 Subject: [PATCH] Enable iterating over validator's parameters with a callback This is how we'll construct parameters interactively. We need to lookup the definition, and provide a data representation for it. --- .../aiken-project/src/blueprint/validator.rs | 39 ++++++++++++++++++- crates/aiken-project/src/lib.rs | 37 +++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/crates/aiken-project/src/blueprint/validator.rs b/crates/aiken-project/src/blueprint/validator.rs index 3804b2c6..826c3f8c 100644 --- a/crates/aiken-project/src/blueprint/validator.rs +++ b/crates/aiken-project/src/blueprint/validator.rs @@ -5,6 +5,7 @@ use super::{ schema::{Annotated, Schema}, }; use crate::module::{CheckedModule, CheckedModules}; +use std::rc::Rc; use aiken_lang::{ ast::{TypedArg, TypedFunction, TypedValidator}, @@ -12,7 +13,10 @@ use aiken_lang::{ }; use miette::NamedSource; use serde; -use uplc::ast::{DeBruijn, Program, Term}; +use uplc::{ + ast::{Constant, DeBruijn, Program, Term}, + PlutusData, +}; #[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)] pub struct Validator { @@ -174,6 +178,39 @@ impl Validator { } } } + + pub fn ask_next_parameter( + &self, + definitions: &Definitions>, + ask: F, + ) -> Result, Error> + where + F: Fn(&Annotated, &Definitions>) -> Result, + { + match self.parameters.split_first() { + None => Err(Error::NoParametersToApply), + Some((head, _)) => { + let schema = definitions + .lookup(&head.schema) + .map(|s| { + Ok(Annotated { + title: s.title.clone().or_else(|| head.title.clone()), + description: s.description.clone(), + annotated: s.annotated.clone(), + }) + }) + .unwrap_or_else(|| { + Err(Error::UnresolvedSchemaReference { + reference: head.schema.clone(), + }) + })?; + + let data = ask(&schema, definitions)?; + + Ok(Term::Constant(Rc::new(Constant::Data(data.clone())))) + } + } + } } #[cfg(test)] diff --git a/crates/aiken-project/src/lib.rs b/crates/aiken-project/src/lib.rs index 72711b0d..bdab5a11 100644 --- a/crates/aiken-project/src/lib.rs +++ b/crates/aiken-project/src/lib.rs @@ -15,7 +15,11 @@ pub mod telemetry; #[cfg(test)] mod tests; -use crate::blueprint::Blueprint; +use crate::blueprint::{ + definitions::Definitions, + schema::{Annotated, Schema}, + Blueprint, +}; use aiken_lang::{ ast::{Definition, Function, ModuleKind, Tracing, TypedDataType, TypedFunction, Validator}, builtins, @@ -44,6 +48,7 @@ use telemetry::EventListener; use uplc::{ ast::{DeBruijn, Name, Program, Term}, machine::cost_model::ExBudget, + PlutusData, }; use crate::{ @@ -416,6 +421,36 @@ where }) } + pub fn construct_parameter_incrementally( + &self, + title: Option<&String>, + ask: F, + ) -> Result, Error> + where + F: Fn( + &Annotated, + &Definitions>, + ) -> Result, + { + // Read blueprint + let blueprint = File::open(self.blueprint_path()) + .map_err(|_| blueprint::error::Error::InvalidOrMissingFile)?; + let blueprint: Blueprint = serde_json::from_reader(BufReader::new(blueprint))?; + + // Construct parameter + let when_too_many = + |known_validators| Error::MoreThanOneValidatorFound { known_validators }; + let when_missing = |known_validators| Error::NoValidatorNotFound { known_validators }; + + let term = blueprint.with_validator(title, when_too_many, when_missing, |validator| { + validator + .ask_next_parameter(&blueprint.definitions, &ask) + .map_err(|e| e.into()) + })?; + + Ok(term) + } + pub fn apply_parameter( &self, title: Option<&String>,