Skip to content

Commit fb93fa5

Browse files
authored
Merge pull request #7 from mlabs-haskell/szg251/change-builtins
Update/fix LambdaBuffer LamVal builtins
2 parents dca3242 + 26609a4 commit fb93fa5

File tree

13 files changed

+255
-109
lines changed

13 files changed

+255
-109
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ edition = "2021"
77

88
[dependencies]
99
proptest = "1.3.1"
10-
lbr-prelude = { git = "https://github.com/mlabs-haskell/lambda-buffers.git", optional = true }
10+
lbr-prelude = { git = "https://github.com/mlabs-haskell/lambda-buffers.git", rev = "59d3fb6422fef707c66fb83c2bd29327371d9bd3", optional = true }
1111
serde_json = { version = "1.0.107", features = [
1212
"arbitrary_precision",
1313
], optional = true }

src/generators/correct/v1.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::v1::address::{
1010
use crate::v1::crypto::{Ed25519PubKeyHash, LedgerBytes};
1111
use crate::v1::datum::{Datum, DatumHash};
1212
use crate::v1::interval::{Extended, LowerBound, PlutusInterval, UpperBound};
13-
use crate::v1::redeemer::Redeemer;
13+
use crate::v1::redeemer::{Redeemer, RedeemerHash};
1414
use crate::v1::script::{MintingPolicyHash, ScriptHash, ValidatorHash};
1515
use crate::v1::transaction::{
1616
POSIXTime, TransactionHash, TransactionInput, TransactionOutput, TxInInfo,
@@ -144,6 +144,11 @@ pub fn arb_redeemer() -> impl Strategy<Value = Redeemer> {
144144
arb_plutus_data().prop_map(Redeemer)
145145
}
146146

147+
/// Strategy to generate a Datum hash
148+
pub fn arb_redeemer_hash() -> impl Strategy<Value = RedeemerHash> {
149+
arb_ledger_bytes(32).prop_map(RedeemerHash)
150+
}
151+
147152
/// Strategy to generate an Extended set
148153
pub fn arb_extended<T>(element: T) -> impl Strategy<Value = Extended<T::Value>>
149154
where

src/lamval.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::plutus_data::{self, PlutusData, PlutusDataError};
2+
use num_bigint::BigInt;
3+
4+
pub fn case_plutus_data<'a, T: 'a>(
5+
x0: Box<dyn 'a + FnOnce(&'a BigInt) -> Box<dyn 'a + FnOnce(&'a Vec<PlutusData>) -> T>>,
6+
) -> Box<
7+
dyn 'a
8+
+ FnOnce(
9+
Box<dyn FnOnce(&'a Vec<PlutusData>) -> T>,
10+
) -> Box<
11+
dyn 'a
12+
+ FnOnce(
13+
Box<dyn FnOnce(&'a BigInt) -> T>,
14+
) -> Box<
15+
dyn 'a
16+
+ FnOnce(
17+
Box<dyn FnOnce(&'a PlutusData) -> T>,
18+
) -> Box<dyn 'a + FnOnce(&'a PlutusData) -> T>,
19+
>,
20+
>,
21+
> {
22+
Box::new(move |x1| {
23+
Box::new(move |x2| {
24+
Box::new(move |x3| {
25+
Box::new(move |x4| plutus_data::case_plutus_data(x0, x1, x2, x3, x4))
26+
})
27+
})
28+
})
29+
}
30+
31+
pub fn constr(tag: u32) -> Box<dyn Fn(Vec<PlutusData>) -> PlutusData> {
32+
Box::new(move |fields| PlutusData::Constr(BigInt::from(tag), fields.clone()))
33+
}
34+
35+
/// Fail PlutusData parsing with an internal error
36+
pub fn fail_parse<T>() -> Result<T, PlutusDataError> {
37+
Err(PlutusDataError::InternalError(
38+
"Failed to parse PlutusData".to_owned(),
39+
))
40+
}
41+
42+
/// Curried Result::and_then function
43+
pub fn bind_parse<'a, A: 'a, B: 'a>(
44+
x: Result<A, PlutusDataError>,
45+
) -> Box<
46+
dyn FnOnce(Box<dyn Fn(&A) -> Result<B, PlutusDataError> + 'a>) -> Result<B, PlutusDataError>
47+
+ 'a,
48+
> {
49+
Box::new(move |f| x.and_then(|x1| f(&x1)))
50+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
pub(crate) mod feature_traits;
22
pub mod generators;
3+
#[cfg(feature = "lbf")]
4+
pub mod lamval;
35
pub mod plutus_data;
46
pub mod v1;
57
pub mod v2;

src/plutus_data.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,44 @@ pub enum PlutusData {
1919
Bytes(Vec<u8>),
2020
}
2121

22+
impl PlutusData {
23+
pub fn constr(tag: u32, fields: Vec<PlutusData>) -> Self {
24+
PlutusData::Constr(BigInt::from(tag), fields)
25+
}
26+
27+
pub fn map(fields: Vec<(PlutusData, PlutusData)>) -> Self {
28+
PlutusData::Map(fields)
29+
}
30+
31+
pub fn list(fields: Vec<PlutusData>) -> Self {
32+
PlutusData::List(fields)
33+
}
34+
35+
pub fn integer(value: u32) -> Self {
36+
PlutusData::Integer(BigInt::from(value))
37+
}
38+
39+
pub fn bytes(value: Vec<u8>) -> Self {
40+
PlutusData::Bytes(value)
41+
}
42+
}
43+
44+
/// Deserialise a Plutus data using parsers for each variant
45+
pub fn case_plutus_data<'a, T>(
46+
ctor_case: impl FnOnce(&'a BigInt) -> Box<dyn 'a + FnOnce(&'a Vec<PlutusData>) -> T>,
47+
list_case: impl FnOnce(&'a Vec<PlutusData>) -> T,
48+
int_case: impl FnOnce(&'a BigInt) -> T,
49+
other_case: impl FnOnce(&'a PlutusData) -> T,
50+
pd: &'a PlutusData,
51+
) -> T {
52+
match pd {
53+
PlutusData::Constr(tag, args) => ctor_case(&tag)(&args),
54+
PlutusData::List(args) => list_case(&args),
55+
PlutusData::Integer(i) => int_case(&i),
56+
other => other_case(&other),
57+
}
58+
}
59+
2260
pub trait IsPlutusData {
2361
fn to_plutus_data(&self) -> PlutusData;
2462

src/v1/address.rs

Lines changed: 70 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -112,40 +112,46 @@ impl IsPlutusData for Credential {
112112

113113
#[cfg(feature = "lbf")]
114114
impl Json for Credential {
115-
fn to_json(&self) -> Result<serde_json::Value, Error> {
115+
fn to_json(&self) -> serde_json::Value {
116116
match self {
117-
Credential::PubKey(pkh) => Ok(json::sum_constructor(
118-
"PubKeyCredential",
119-
vec![pkh.to_json()?],
120-
)),
121-
Credential::Script(val_hash) => Ok(json::sum_constructor(
122-
"ScriptCredential",
123-
vec![val_hash.to_json()?],
124-
)),
117+
Credential::PubKey(pkh) => {
118+
json::json_constructor("PubKeyCredential", &vec![pkh.to_json()])
119+
}
120+
Credential::Script(val_hash) => {
121+
json::json_constructor("ScriptCredential", &vec![val_hash.to_json()])
122+
}
125123
}
126124
}
127125

128-
fn from_json(value: serde_json::Value) -> Result<Self, Error> {
129-
json::sum_parser(&value).and_then(|obj| match obj {
130-
("PubKeyCredential", ctor_fields) => match &ctor_fields[..] {
131-
[pkh] => Ok(Credential::PubKey(Json::from_json(pkh.clone())?)),
132-
_ => Err(Error::UnexpectedArrayLength {
133-
wanted: 1,
134-
got: ctor_fields.len(),
135-
}),
136-
},
137-
("ScriptCredential", ctor_fields) => match &ctor_fields[..] {
138-
[val_hash] => Ok(Credential::Script(Json::from_json(val_hash.clone())?)),
139-
_ => Err(Error::UnexpectedArrayLength {
140-
wanted: 1,
141-
got: ctor_fields.len(),
142-
}),
143-
},
144-
_ => Err(Error::UnexpectedJsonInvariant {
145-
wanted: "constructor names (Nothing, Just)".to_owned(),
146-
got: "unknown constructor name".to_owned(),
147-
}),
148-
})
126+
fn from_json(value: &serde_json::Value) -> Result<Self, Error> {
127+
json::case_json_constructor(
128+
"Plutus.V1.Credential",
129+
vec![
130+
(
131+
"PubKeyCredential",
132+
Box::new(|ctor_fields| match &ctor_fields[..] {
133+
[pkh] => Ok(Credential::PubKey(Json::from_json(pkh)?)),
134+
_ => Err(Error::UnexpectedArrayLength {
135+
wanted: 1,
136+
got: ctor_fields.len(),
137+
parser: "Plutus.V1.Credential".to_owned(),
138+
}),
139+
}),
140+
),
141+
(
142+
"ScriptCredential",
143+
Box::new(|ctor_fields| match &ctor_fields[..] {
144+
[val_hash] => Ok(Credential::Script(Json::from_json(val_hash)?)),
145+
_ => Err(Error::UnexpectedArrayLength {
146+
wanted: 1,
147+
got: ctor_fields.len(),
148+
parser: "Plutus.V1.Credential".to_owned(),
149+
}),
150+
}),
151+
),
152+
],
153+
value,
154+
)
149155
}
150156
}
151157

@@ -211,41 +217,46 @@ impl IsPlutusData for StakingCredential {
211217

212218
#[cfg(feature = "lbf")]
213219
impl Json for StakingCredential {
214-
fn to_json(&self) -> Result<serde_json::Value, Error> {
220+
fn to_json(&self) -> serde_json::Value {
215221
match self {
216222
StakingCredential::Hash(pkh) => {
217-
Ok(json::sum_constructor("StakingHash", vec![pkh.to_json()?]))
223+
json::json_constructor("StakingHash", &vec![pkh.to_json()])
224+
}
225+
StakingCredential::Pointer(val_hash) => {
226+
json::json_constructor("StakingPtr", &vec![val_hash.to_json()])
218227
}
219-
StakingCredential::Pointer(val_hash) => Ok(json::sum_constructor(
220-
"StakingPtr",
221-
vec![val_hash.to_json()?],
222-
)),
223228
}
224229
}
225230

226-
fn from_json(value: serde_json::Value) -> Result<Self, Error> {
227-
json::sum_parser(&value).and_then(|obj| match obj {
228-
("StakingHash", ctor_fields) => match &ctor_fields[..] {
229-
[pkh] => Ok(StakingCredential::Hash(Json::from_json(pkh.clone())?)),
230-
_ => Err(Error::UnexpectedArrayLength {
231-
wanted: 1,
232-
got: ctor_fields.len(),
233-
}),
234-
},
235-
("StakingPtr", ctor_fields) => match &ctor_fields[..] {
236-
[val_hash] => Ok(StakingCredential::Pointer(Json::from_json(
237-
val_hash.clone(),
238-
)?)),
239-
_ => Err(Error::UnexpectedArrayLength {
240-
wanted: 1,
241-
got: ctor_fields.len(),
242-
}),
243-
},
244-
_ => Err(Error::UnexpectedJsonInvariant {
245-
wanted: "constructor names (Nothing, Just)".to_owned(),
246-
got: "unknown constructor name".to_owned(),
247-
}),
248-
})
231+
fn from_json(value: &serde_json::Value) -> Result<Self, Error> {
232+
json::case_json_constructor(
233+
"Plutus.V1.StakingCredential",
234+
vec![
235+
(
236+
"StakingHash",
237+
Box::new(|ctor_fields| match &ctor_fields[..] {
238+
[pkh] => Ok(StakingCredential::Hash(Json::from_json(pkh)?)),
239+
_ => Err(Error::UnexpectedArrayLength {
240+
wanted: 1,
241+
got: ctor_fields.len(),
242+
parser: "Plutus.V1.StakingCredential".to_owned(),
243+
}),
244+
}),
245+
),
246+
(
247+
"StakingPtr",
248+
Box::new(|ctor_fields| match &ctor_fields[..] {
249+
[val_hash] => Ok(StakingCredential::Pointer(Json::from_json(&val_hash)?)),
250+
_ => Err(Error::UnexpectedArrayLength {
251+
wanted: 1,
252+
got: ctor_fields.len(),
253+
parser: "Plutus.V1.StakingCredential".to_owned(),
254+
}),
255+
}),
256+
),
257+
],
258+
value,
259+
)
249260
}
250261
}
251262

src/v1/crypto.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,18 @@ impl IsPlutusData for LedgerBytes {
101101

102102
#[cfg(feature = "lbf")]
103103
impl Json for LedgerBytes {
104-
fn to_json(&self) -> Result<serde_json::Value, Error> {
104+
fn to_json(&self) -> serde_json::Value {
105105
String::to_json(&HEXLOWER.encode(&self.0))
106106
}
107107

108-
fn from_json(value: serde_json::Value) -> Result<Self, Error> {
108+
fn from_json(value: &serde_json::Value) -> Result<Self, Error> {
109109
let bytes = String::from_json(value).and_then(|str| {
110110
HEXLOWER
111111
.decode(&str.into_bytes())
112112
.map_err(|_| Error::UnexpectedJsonInvariant {
113113
wanted: "base16 string".to_owned(),
114114
got: "unexpected string".to_owned(),
115+
parser: "Plutus.V1.Bytes".to_owned(),
115116
})
116117
})?;
117118

src/v1/redeemer.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Types related to Plutus Redeemers
22
use crate::plutus_data::{IsPlutusData, PlutusData, PlutusDataError};
3+
use crate::v1::crypto::LedgerBytes;
34
#[cfg(feature = "lbf")]
45
use lbr_prelude::json::Json;
56
#[cfg(feature = "serde")]
@@ -21,3 +22,19 @@ impl IsPlutusData for Redeemer {
2122
IsPlutusData::from_plutus_data(data).map(Self)
2223
}
2324
}
25+
26+
/// blake2b-256 hash of a datum
27+
#[derive(Clone, Debug, PartialEq, Eq)]
28+
#[cfg_attr(feature = "lbf", derive(Json))]
29+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30+
pub struct RedeemerHash(pub LedgerBytes);
31+
32+
impl IsPlutusData for RedeemerHash {
33+
fn to_plutus_data(&self) -> PlutusData {
34+
self.0.to_plutus_data()
35+
}
36+
37+
fn from_plutus_data(data: &PlutusData) -> Result<Self, PlutusDataError> {
38+
IsPlutusData::from_plutus_data(data).map(Self)
39+
}
40+
}

src/v1/value.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ impl IsPlutusData for CurrencySymbol {
4545

4646
#[cfg(feature = "lbf")]
4747
impl Json for CurrencySymbol {
48-
fn to_json(&self) -> Result<serde_json::Value, Error> {
48+
fn to_json(&self) -> serde_json::Value {
4949
match self {
50-
CurrencySymbol::Ada => Ok(serde_json::Value::String(String::new())),
50+
CurrencySymbol::Ada => serde_json::Value::String(String::new()),
5151
CurrencySymbol::NativeToken(policy_hash) => policy_hash.to_json(),
5252
}
5353
}
5454

55-
fn from_json(value: serde_json::Value) -> Result<Self, Error> {
55+
fn from_json(value: &serde_json::Value) -> Result<Self, Error> {
5656
match value.clone() {
5757
serde_json::Value::String(str) => {
5858
if str.is_empty() {
@@ -63,7 +63,8 @@ impl Json for CurrencySymbol {
6363
}
6464
_ => Err(Error::UnexpectedJsonType {
6565
wanted: JsonType::String,
66-
got: JsonType::from(&value),
66+
got: JsonType::from(value),
67+
parser: "Plutus.V1.CurrencySymbol".to_owned(),
6768
}),
6869
}
6970
}

0 commit comments

Comments
 (0)