Fix Plutus v3 validator hash calculation in blueprint.
This commit is contained in:
parent
445ffc483d
commit
508d88035b
|
@ -5,14 +5,13 @@ pub mod parameter;
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod validator;
|
pub mod validator;
|
||||||
|
|
||||||
pub use error::Error;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{self, Config, PlutusVersion},
|
config::{self, Config, PlutusVersion},
|
||||||
module::CheckedModules,
|
module::CheckedModules,
|
||||||
};
|
};
|
||||||
use aiken_lang::gen_uplc::CodeGenerator;
|
use aiken_lang::gen_uplc::CodeGenerator;
|
||||||
use definitions::Definitions;
|
use definitions::Definitions;
|
||||||
|
pub 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;
|
||||||
|
@ -70,7 +69,7 @@ impl Blueprint {
|
||||||
let validators: Result<Vec<_>, Error> = modules
|
let validators: Result<Vec<_>, Error> = modules
|
||||||
.validators()
|
.validators()
|
||||||
.flat_map(|(validator, def)| {
|
.flat_map(|(validator, def)| {
|
||||||
Validator::from_checked_module(modules, generator, validator, def)
|
Validator::from_checked_module(modules, generator, validator, def, &config.plutus)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|result| {
|
.map(|result| {
|
||||||
result.map(|mut schema| {
|
result.map(|mut schema| {
|
||||||
|
|
|
@ -9,13 +9,14 @@ use crate::module::{CheckedModule, CheckedModules};
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{Annotation, TypedArg, TypedFunction, TypedValidator},
|
ast::{Annotation, TypedArg, TypedFunction, TypedValidator},
|
||||||
gen_uplc::CodeGenerator,
|
gen_uplc::CodeGenerator,
|
||||||
|
plutus_version::PlutusVersion,
|
||||||
tipo::Type,
|
tipo::Type,
|
||||||
};
|
};
|
||||||
use miette::NamedSource;
|
use miette::NamedSource;
|
||||||
use serde;
|
use serde;
|
||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use uplc::{
|
use uplc::{
|
||||||
ast::{Constant, DeBruijn, Program},
|
ast::{Constant, SerializableProgram},
|
||||||
PlutusData,
|
PlutusData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ pub struct Validator {
|
||||||
pub parameters: Vec<Parameter>,
|
pub parameters: Vec<Parameter>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub program: Program<DeBruijn>,
|
pub program: SerializableProgram,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Definitions::is_empty")]
|
#[serde(skip_serializing_if = "Definitions::is_empty")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -49,6 +50,7 @@ impl Validator {
|
||||||
generator: &mut CodeGenerator,
|
generator: &mut CodeGenerator,
|
||||||
module: &CheckedModule,
|
module: &CheckedModule,
|
||||||
def: &TypedValidator,
|
def: &TypedValidator,
|
||||||
|
plutus_version: &PlutusVersion,
|
||||||
) -> Vec<Result<Validator, Error>> {
|
) -> Vec<Result<Validator, Error>> {
|
||||||
let is_multi_validator = def.other_fun.is_some();
|
let is_multi_validator = def.other_fun.is_some();
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ impl Validator {
|
||||||
&def.fun,
|
&def.fun,
|
||||||
is_multi_validator,
|
is_multi_validator,
|
||||||
&mut program,
|
&mut program,
|
||||||
|
plutus_version,
|
||||||
)];
|
)];
|
||||||
|
|
||||||
if let Some(ref other_func) = def.other_fun {
|
if let Some(ref other_func) = def.other_fun {
|
||||||
|
@ -73,12 +76,14 @@ impl Validator {
|
||||||
other_func,
|
other_func,
|
||||||
is_multi_validator,
|
is_multi_validator,
|
||||||
&mut program,
|
&mut program,
|
||||||
|
plutus_version,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
validators
|
validators
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn create_validator_blueprint(
|
fn create_validator_blueprint(
|
||||||
generator: &mut CodeGenerator,
|
generator: &mut CodeGenerator,
|
||||||
modules: &CheckedModules,
|
modules: &CheckedModules,
|
||||||
|
@ -87,6 +92,7 @@ impl Validator {
|
||||||
func: &TypedFunction,
|
func: &TypedFunction,
|
||||||
is_multi_validator: bool,
|
is_multi_validator: bool,
|
||||||
program: &mut MemoProgram,
|
program: &mut MemoProgram,
|
||||||
|
plutus_version: &PlutusVersion,
|
||||||
) -> Result<Validator, 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());
|
||||||
|
@ -168,7 +174,11 @@ impl Validator {
|
||||||
parameters,
|
parameters,
|
||||||
datum,
|
datum,
|
||||||
redeemer,
|
redeemer,
|
||||||
program: program.get(generator, def, &module.name),
|
program: match plutus_version {
|
||||||
|
PlutusVersion::V1 => SerializableProgram::PlutusV1Program,
|
||||||
|
PlutusVersion::V2 => SerializableProgram::PlutusV2Program,
|
||||||
|
PlutusVersion::V3 => SerializableProgram::PlutusV3Program,
|
||||||
|
}(program.get(generator, def, &module.name)),
|
||||||
definitions,
|
definitions,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -208,7 +218,7 @@ impl Validator {
|
||||||
Some((head, tail)) => {
|
Some((head, tail)) => {
|
||||||
head.validate(definitions, &Constant::Data(arg.clone()))?;
|
head.validate(definitions, &Constant::Data(arg.clone()))?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
program: self.program.apply_data(arg.clone()),
|
program: self.program.map(|program| program.apply_data(arg.clone())),
|
||||||
parameters: tail.to_vec(),
|
parameters: tail.to_vec(),
|
||||||
..self
|
..self
|
||||||
})
|
})
|
||||||
|
@ -284,7 +294,7 @@ mod tests {
|
||||||
.next()
|
.next()
|
||||||
.expect("source code did no yield any validator");
|
.expect("source code did no yield any validator");
|
||||||
|
|
||||||
let validators = Validator::from_checked_module(&modules, &mut generator, validator, def);
|
let validators = Validator::from_checked_module(&modules, &mut generator, validator, def, &PlutusVersion::default());
|
||||||
|
|
||||||
if validators.len() > 1 {
|
if validators.len() > 1 {
|
||||||
panic!("Multi-validator given to test bench. Don't do that.")
|
panic!("Multi-validator given to test bench. Don't do that.")
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
use aiken_lang::{ast::TypedFunction, gen_uplc::CodeGenerator};
|
|
||||||
use miette::NamedSource;
|
|
||||||
use uplc::ast::{DeBruijn, Program};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
blueprint::{
|
blueprint::{
|
||||||
self,
|
self,
|
||||||
|
@ -11,6 +7,9 @@ use crate::{
|
||||||
},
|
},
|
||||||
module::{CheckedModule, CheckedModules},
|
module::{CheckedModule, CheckedModules},
|
||||||
};
|
};
|
||||||
|
use aiken_lang::{ast::TypedFunction, gen_uplc::CodeGenerator, plutus_version::PlutusVersion};
|
||||||
|
use miette::NamedSource;
|
||||||
|
use uplc::ast::SerializableProgram;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Export {
|
pub struct Export {
|
||||||
|
@ -24,7 +23,7 @@ pub struct Export {
|
||||||
pub parameters: Vec<Parameter>,
|
pub parameters: Vec<Parameter>,
|
||||||
|
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub program: Program<DeBruijn>,
|
pub program: SerializableProgram,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Definitions::is_empty")]
|
#[serde(skip_serializing_if = "Definitions::is_empty")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -37,6 +36,7 @@ impl Export {
|
||||||
module: &CheckedModule,
|
module: &CheckedModule,
|
||||||
generator: &mut CodeGenerator,
|
generator: &mut CodeGenerator,
|
||||||
modules: &CheckedModules,
|
modules: &CheckedModules,
|
||||||
|
plutus_version: &PlutusVersion,
|
||||||
) -> Result<Export, blueprint::Error> {
|
) -> Result<Export, blueprint::Error> {
|
||||||
let mut definitions = Definitions::new();
|
let mut definitions = Definitions::new();
|
||||||
|
|
||||||
|
@ -64,10 +64,16 @@ impl Export {
|
||||||
})
|
})
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let program = generator
|
let program = match plutus_version {
|
||||||
.generate_raw(&func.body, &func.arguments, &module.name)
|
PlutusVersion::V1 => SerializableProgram::PlutusV1Program,
|
||||||
.to_debruijn()
|
PlutusVersion::V2 => SerializableProgram::PlutusV2Program,
|
||||||
.unwrap();
|
PlutusVersion::V3 => SerializableProgram::PlutusV3Program,
|
||||||
|
}(
|
||||||
|
generator
|
||||||
|
.generate_raw(&func.body, &func.arguments, &module.name)
|
||||||
|
.to_debruijn()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(Export {
|
Ok(Export {
|
||||||
name: format!("{}.{}", &module.name, &func.name),
|
name: format!("{}.{}", &module.name, &func.name),
|
||||||
|
@ -86,6 +92,7 @@ mod tests {
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
self,
|
self,
|
||||||
ast::{TraceLevel, Tracing},
|
ast::{TraceLevel, Tracing},
|
||||||
|
plutus_version::PlutusVersion,
|
||||||
};
|
};
|
||||||
|
|
||||||
macro_rules! assert_export {
|
macro_rules! assert_export {
|
||||||
|
@ -103,7 +110,7 @@ mod tests {
|
||||||
.next()
|
.next()
|
||||||
.expect("source code did no yield any exports");
|
.expect("source code did no yield any exports");
|
||||||
|
|
||||||
let export = Export::from_function(func, module, &mut generator, &modules);
|
let export = Export::from_function(func, module, &mut generator, &modules, &PlutusVersion::default());
|
||||||
|
|
||||||
match export {
|
match export {
|
||||||
Err(e) => insta::with_settings!({
|
Err(e) => insta::with_settings!({
|
||||||
|
|
|
@ -40,7 +40,6 @@ use aiken_lang::{
|
||||||
format::{Formatter, MAX_COLUMNS},
|
format::{Formatter, MAX_COLUMNS},
|
||||||
gen_uplc::CodeGenerator,
|
gen_uplc::CodeGenerator,
|
||||||
line_numbers::LineNumbers,
|
line_numbers::LineNumbers,
|
||||||
plutus_version::PlutusVersion,
|
|
||||||
tipo::{Type, TypeInfo},
|
tipo::{Type, TypeInfo},
|
||||||
IdGenerator,
|
IdGenerator,
|
||||||
};
|
};
|
||||||
|
@ -50,8 +49,7 @@ use miette::NamedSource;
|
||||||
use options::{CodeGenMode, Options};
|
use options::{CodeGenMode, Options};
|
||||||
use package_name::PackageName;
|
use package_name::PackageName;
|
||||||
use pallas_addresses::{Address, Network, ShelleyAddress, ShelleyDelegationPart, StakePayload};
|
use pallas_addresses::{Address, Network, ShelleyAddress, ShelleyDelegationPart, StakePayload};
|
||||||
use pallas_primitives::conway::{self as cardano, PolicyId};
|
use pallas_primitives::conway::PolicyId;
|
||||||
use pallas_traverse::ComputeHash;
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeSet, HashMap},
|
collections::{BTreeSet, HashMap},
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
|
@ -298,7 +296,7 @@ where
|
||||||
let path = dir.clone().join(format!("{}.uplc", validator.title));
|
let path = dir.clone().join(format!("{}.uplc", validator.title));
|
||||||
|
|
||||||
let program = &validator.program;
|
let program = &validator.program;
|
||||||
let program: Program<Name> = program.try_into().unwrap();
|
let program: Program<Name> = program.inner().try_into().unwrap();
|
||||||
|
|
||||||
fs::write(&path, program.to_pretty()).map_err(|error| Error::FileIo { error, path })?;
|
fs::write(&path, program.to_pretty()).map_err(|error| Error::FileIo { error, path })?;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +488,7 @@ where
|
||||||
Network::Testnet
|
Network::Testnet
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(validator.program.address(
|
Ok(validator.program.inner().address(
|
||||||
network,
|
network,
|
||||||
delegation_part.to_owned(),
|
delegation_part.to_owned(),
|
||||||
&self.config.plutus.into(),
|
&self.config.plutus.into(),
|
||||||
|
@ -520,15 +518,7 @@ where
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
Err(blueprint::error::Error::ParameterizedValidator { n }.into())
|
||||||
} else {
|
} else {
|
||||||
let cbor = validator.program.to_cbor().unwrap();
|
Ok(validator.program.compiled_code_and_hash().1)
|
||||||
|
|
||||||
let validator_hash = match self.config.plutus {
|
|
||||||
PlutusVersion::V1 => cardano::PlutusV1Script(cbor.into()).compute_hash(),
|
|
||||||
PlutusVersion::V2 => cardano::PlutusV2Script(cbor.into()).compute_hash(),
|
|
||||||
PlutusVersion::V3 => cardano::PlutusV3Script(cbor.into()).compute_hash(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(validator_hash)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -552,7 +542,13 @@ where
|
||||||
.map(|(checked_module, func)| {
|
.map(|(checked_module, func)| {
|
||||||
let mut generator = self.new_generator(tracing);
|
let mut generator = self.new_generator(tracing);
|
||||||
|
|
||||||
Export::from_function(func, checked_module, &mut generator, &self.checked_modules)
|
Export::from_function(
|
||||||
|
func,
|
||||||
|
checked_module,
|
||||||
|
&mut generator,
|
||||||
|
&self.checked_modules,
|
||||||
|
&self.config.plutus,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.transpose()?
|
.transpose()?
|
||||||
.ok_or_else(|| Error::ExportNotFound {
|
.ok_or_else(|| Error::ExportNotFound {
|
||||||
|
|
|
@ -83,7 +83,7 @@ pub fn exec(
|
||||||
let result =
|
let result =
|
||||||
blueprint.with_validator(title, when_too_many, when_missing, |validator| match to {
|
blueprint.with_validator(title, when_too_many, when_missing, |validator| match to {
|
||||||
Format::CardanoCli => {
|
Format::CardanoCli => {
|
||||||
let cbor_bytes = validator.program.to_cbor().unwrap();
|
let cbor_bytes = validator.program.inner().to_cbor().unwrap();
|
||||||
|
|
||||||
let mut double_cbor_bytes = Vec::new();
|
let mut double_cbor_bytes = Vec::new();
|
||||||
|
|
||||||
|
|
|
@ -111,38 +111,99 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for Program<DeBruijn> {
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum SerializableProgram {
|
||||||
|
PlutusV1Program(Program<DeBruijn>),
|
||||||
|
PlutusV2Program(Program<DeBruijn>),
|
||||||
|
PlutusV3Program(Program<DeBruijn>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SerializableProgram {
|
||||||
|
pub fn inner(&self) -> &Program<DeBruijn> {
|
||||||
|
use SerializableProgram::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
PlutusV1Program(program) => program,
|
||||||
|
PlutusV2Program(program) => program,
|
||||||
|
PlutusV3Program(program) => program,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn map<F>(self, f: F) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(Program<DeBruijn>) -> Program<DeBruijn>,
|
||||||
|
{
|
||||||
|
use SerializableProgram::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
PlutusV1Program(program) => PlutusV1Program(f(program)),
|
||||||
|
PlutusV2Program(program) => PlutusV2Program(f(program)),
|
||||||
|
PlutusV3Program(program) => PlutusV3Program(f(program)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compiled_code_and_hash(&self) -> (String, pallas_crypto::hash::Hash<28>) {
|
||||||
|
use SerializableProgram::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
PlutusV1Program(pgrm) => {
|
||||||
|
let cbor = pgrm.to_cbor().unwrap();
|
||||||
|
let compiled_code = hex::encode(&cbor);
|
||||||
|
let hash = conway::PlutusV1Script(cbor.into()).compute_hash();
|
||||||
|
(compiled_code, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
PlutusV2Program(pgrm) => {
|
||||||
|
let cbor = pgrm.to_cbor().unwrap();
|
||||||
|
let compiled_code = hex::encode(&cbor);
|
||||||
|
let hash = conway::PlutusV2Script(cbor.into()).compute_hash();
|
||||||
|
(compiled_code, hash)
|
||||||
|
}
|
||||||
|
|
||||||
|
PlutusV3Program(pgrm) => {
|
||||||
|
let cbor = pgrm.to_cbor().unwrap();
|
||||||
|
let compiled_code = hex::encode(&cbor);
|
||||||
|
let hash = conway::PlutusV3Script(cbor.into()).compute_hash();
|
||||||
|
(compiled_code, hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for SerializableProgram {
|
||||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||||
let cbor = self.to_cbor().unwrap();
|
let (compiled_code, hash) = self.compiled_code_and_hash();
|
||||||
let mut s = serializer.serialize_struct("Program<DeBruijn>", 2)?;
|
let mut s = serializer.serialize_struct("Program<DeBruijn>", 2)?;
|
||||||
s.serialize_field("compiledCode", &hex::encode(&cbor))?;
|
s.serialize_field("compiledCode", &compiled_code)?;
|
||||||
s.serialize_field("hash", &conway::PlutusV2Script(cbor.into()).compute_hash())?;
|
s.serialize_field("hash", &hash)?;
|
||||||
s.end()
|
s.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Deserialize<'a> for Program<DeBruijn> {
|
impl<'a> Deserialize<'a> for SerializableProgram {
|
||||||
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
|
fn deserialize<D: Deserializer<'a>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
#[serde(field_identifier, rename_all = "camelCase")]
|
#[serde(field_identifier, rename_all = "camelCase")]
|
||||||
enum Fields {
|
enum Fields {
|
||||||
CompiledCode,
|
CompiledCode,
|
||||||
|
Hash,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ProgramVisitor;
|
struct ProgramVisitor;
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for ProgramVisitor {
|
impl<'a> Visitor<'a> for ProgramVisitor {
|
||||||
type Value = Program<DeBruijn>;
|
type Value = SerializableProgram;
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||||
formatter.write_str("Program<Visitor>")
|
formatter.write_str("validator")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_map<V>(self, mut map: V) -> Result<Program<DeBruijn>, V::Error>
|
fn visit_map<V>(self, mut map: V) -> Result<SerializableProgram, V::Error>
|
||||||
where
|
where
|
||||||
V: MapAccess<'a>,
|
V: MapAccess<'a>,
|
||||||
{
|
{
|
||||||
let mut compiled_code: Option<String> = None;
|
let mut compiled_code: Option<String> = None;
|
||||||
|
let mut hash: Option<String> = None;
|
||||||
while let Some(key) = map.next_key()? {
|
while let Some(key) = map.next_key()? {
|
||||||
match key {
|
match key {
|
||||||
Fields::CompiledCode => {
|
Fields::CompiledCode => {
|
||||||
|
@ -151,11 +212,20 @@ impl<'a> Deserialize<'a> for Program<DeBruijn> {
|
||||||
}
|
}
|
||||||
compiled_code = Some(map.next_value()?);
|
compiled_code = Some(map.next_value()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Fields::Hash => {
|
||||||
|
if hash.is_some() {
|
||||||
|
return Err(de::Error::duplicate_field("hash"));
|
||||||
|
}
|
||||||
|
hash = Some(map.next_value()?);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let compiled_code =
|
let compiled_code =
|
||||||
compiled_code.ok_or_else(|| de::Error::missing_field("compiledCode"))?;
|
compiled_code.ok_or_else(|| de::Error::missing_field("compiledCode"))?;
|
||||||
|
|
||||||
|
let hash = hash.ok_or_else(|| de::Error::missing_field("hash"))?;
|
||||||
|
|
||||||
let mut cbor_buffer = Vec::new();
|
let mut cbor_buffer = Vec::new();
|
||||||
let mut flat_buffer = Vec::new();
|
let mut flat_buffer = Vec::new();
|
||||||
|
|
||||||
|
@ -166,10 +236,29 @@ impl<'a> Deserialize<'a> for Program<DeBruijn> {
|
||||||
&"a base16-encoded CBOR-serialized UPLC program",
|
&"a base16-encoded CBOR-serialized UPLC program",
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
.and_then(|program| {
|
||||||
|
let cbor = || program.to_cbor().unwrap().into();
|
||||||
|
|
||||||
|
if conway::PlutusV3Script(cbor()).compute_hash().to_string() == hash {
|
||||||
|
return Ok(SerializableProgram::PlutusV3Program(program));
|
||||||
|
}
|
||||||
|
|
||||||
|
if conway::PlutusV2Script(cbor()).compute_hash().to_string() == hash {
|
||||||
|
return Ok(SerializableProgram::PlutusV2Program(program));
|
||||||
|
}
|
||||||
|
|
||||||
|
if conway::PlutusV1Script(cbor()).compute_hash().to_string() == hash {
|
||||||
|
return Ok(SerializableProgram::PlutusV1Program(program));
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(de::Error::custom(
|
||||||
|
"hash doesn't match any recognisable Plutus version.",
|
||||||
|
))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const FIELDS: &[&str] = &["compiledCode"];
|
const FIELDS: &[&str] = &["compiledCode", "hash"];
|
||||||
deserializer.deserialize_struct("Program<DeBruijn>", FIELDS, ProgramVisitor)
|
deserializer.deserialize_struct("Program<DeBruijn>", FIELDS, ProgramVisitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue