refactor: support roundtrip encoding for script data hash components (#526)
This commit is contained in:
parent
969d5612b7
commit
537cd45c23
9 changed files with 84 additions and 119 deletions
|
|
@ -3,9 +3,8 @@
|
|||
//! Handcrafted, idiomatic rust artifacts based on based on the [Conway CDDL](https://github.com/IntersectMBO/cardano-ledger/blob/master/eras/conway/impl/cddl-files/conway.cddl) file in IntersectMBO repo.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::ops::Deref;
|
||||
|
||||
use pallas_codec::minicbor::{self, decode::Error, Decode, Encode};
|
||||
use pallas_codec::minicbor::{self, Decode, Encode};
|
||||
use pallas_codec::utils::CborWrap;
|
||||
|
||||
pub use crate::{
|
||||
|
|
@ -1278,22 +1277,15 @@ pub struct RedeemersValue {
|
|||
pub ex_units: ExUnits,
|
||||
}
|
||||
|
||||
// TODO: Redeemers needs to be KeepRaw because of script data hash
|
||||
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Redeemers(NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>);
|
||||
|
||||
impl Deref for Redeemers {
|
||||
type Target = NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
pub enum Redeemers {
|
||||
List(MaybeIndefArray<Redeemer>),
|
||||
Map(NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>),
|
||||
}
|
||||
|
||||
impl From<NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>> for Redeemers {
|
||||
fn from(value: NonEmptyKeyValuePairs<RedeemersKey, RedeemersValue>) -> Self {
|
||||
Redeemers(value)
|
||||
Redeemers::Map(value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1301,30 +1293,10 @@ impl<'b, C> minicbor::Decode<'b, C> for Redeemers {
|
|||
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||
match d.datatype()? {
|
||||
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
|
||||
let redeemers: Vec<Redeemer> = d.decode_with(ctx)?;
|
||||
|
||||
let kvs = redeemers
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
(
|
||||
RedeemersKey {
|
||||
tag: x.tag,
|
||||
index: x.index,
|
||||
},
|
||||
RedeemersValue {
|
||||
data: x.data,
|
||||
ex_units: x.ex_units,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.map_err(|_| Error::message("decoding empty redeemers"))?;
|
||||
|
||||
Ok(Self(kvs))
|
||||
Ok(Self::List(d.decode_with(ctx)?))
|
||||
}
|
||||
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
|
||||
Ok(Self(d.decode_with(ctx)?))
|
||||
Ok(Self::Map(d.decode_with(ctx)?))
|
||||
}
|
||||
_ => Err(minicbor::decode::Error::message(
|
||||
"invalid type for redeemers struct",
|
||||
|
|
@ -1339,7 +1311,10 @@ impl<C> minicbor::Encode<C> for Redeemers {
|
|||
e: &mut minicbor::Encoder<W>,
|
||||
ctx: &mut C,
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
e.encode_with(&self.0, ctx)?;
|
||||
match self {
|
||||
Self::List(x) => e.encode_with(x, ctx)?,
|
||||
Self::Map(x) => e.encode_with(x, ctx)?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
use crate::KeyValuePairs;
|
||||
use pallas_codec::minicbor::{
|
||||
self,
|
||||
data::{IanaTag, Tag},
|
||||
Encode,
|
||||
};
|
||||
use pallas_codec::utils::Int;
|
||||
use pallas_codec::{
|
||||
minicbor::{
|
||||
self,
|
||||
data::{IanaTag, Tag},
|
||||
Encode,
|
||||
},
|
||||
utils::MaybeIndefArray,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{fmt, ops::Deref};
|
||||
|
||||
|
|
@ -14,7 +17,7 @@ pub enum PlutusData {
|
|||
Map(KeyValuePairs<PlutusData, PlutusData>),
|
||||
BigInt(BigInt),
|
||||
BoundedBytes(BoundedBytes),
|
||||
Array(Vec<PlutusData>),
|
||||
Array(MaybeIndefArray<PlutusData>),
|
||||
}
|
||||
|
||||
impl<'b, C> minicbor::decode::Decode<'b, C> for PlutusData {
|
||||
|
|
@ -96,11 +99,7 @@ impl<C> minicbor::encode::Encode<C> for PlutusData {
|
|||
e.encode_with(a, ctx)?;
|
||||
}
|
||||
Self::Array(a) => {
|
||||
// we use definite array for empty array or indef array otherwise to match
|
||||
// haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L153
|
||||
// default encoder for a list:
|
||||
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
|
||||
encode_list(a, e, ctx)?;
|
||||
e.encode_with(a, ctx)?;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -182,7 +181,7 @@ impl<C> minicbor::encode::Encode<C> for BigInt {
|
|||
pub struct Constr<A> {
|
||||
pub tag: u64,
|
||||
pub any_constructor: Option<u64>,
|
||||
pub fields: Vec<A>,
|
||||
pub fields: MaybeIndefArray<A>,
|
||||
}
|
||||
|
||||
impl<'b, C, A> minicbor::decode::Decode<'b, C> for Constr<A>
|
||||
|
|
@ -227,22 +226,12 @@ where
|
|||
|
||||
match self.tag {
|
||||
102 => {
|
||||
// definite length array here
|
||||
// https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L152
|
||||
e.array(2)?;
|
||||
e.encode_with(self.any_constructor.unwrap_or_default(), ctx)?;
|
||||
|
||||
// we use definite array for empty array or indef array otherwise to match
|
||||
// haskell implementation https://github.com/input-output-hk/plutus/blob/9538fc9829426b2ecb0628d352e2d7af96ec8204/plutus-core/plutus-core/src/PlutusCore/Data.hs#L144
|
||||
// default encoder for a list:
|
||||
// https://github.com/well-typed/cborg/blob/4bdc818a1f0b35f38bc118a87944630043b58384/serialise/src/Codec/Serialise/Class.hs#L181
|
||||
encode_list(&self.fields, e, ctx)?;
|
||||
let x = (self.any_constructor.unwrap_or_default(), &self.fields);
|
||||
e.encode_with(x, ctx)?;
|
||||
Ok(())
|
||||
}
|
||||
_ => {
|
||||
// we use definite array for empty array or indef array otherwise to match
|
||||
// haskell implementation. See above reference.
|
||||
encode_list(&self.fields, e, ctx)?;
|
||||
e.encode_with(&self.fields, ctx)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -332,22 +321,3 @@ impl<'b, C> minicbor::decode::Decode<'b, C> for BoundedBytes {
|
|||
Ok(BoundedBytes::from(res))
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_list<C, W: minicbor::encode::Write, A: minicbor::encode::Encode<C>>(
|
||||
a: &Vec<A>,
|
||||
e: &mut minicbor::Encoder<W>,
|
||||
ctx: &mut C,
|
||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||
// Mimics default haskell list encoding from cborg:
|
||||
// We use indef array for non-empty arrays but definite 0-length array for empty
|
||||
if a.is_empty() {
|
||||
e.array(0)?;
|
||||
} else {
|
||||
e.begin_array()?;
|
||||
for v in a {
|
||||
e.encode_with(v, ctx)?;
|
||||
}
|
||||
e.end()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue