1use crate::feature_traits::FeatureTraits;
5use crate::generators::correct::primitive::{arb_bool, arb_bytes, arb_integer, arb_natural};
6use crate::plutus_data::PlutusData;
7use crate::v1::address::{
8 Address, CertificateIndex, ChainPointer, Credential, Slot, StakingCredential, TransactionIndex,
9};
10use crate::v1::assoc_map::AssocMap;
11use crate::v1::crypto::{Ed25519PubKeyHash, LedgerBytes, PaymentPubKeyHash, StakePubKeyHash};
12use crate::v1::datum::{Datum, DatumHash};
13use crate::v1::interval::{Extended, Interval, LowerBound, PlutusInterval, UpperBound};
14use crate::v1::redeemer::{Redeemer, RedeemerHash};
15use crate::v1::script::{MintingPolicyHash, ScriptHash, ValidatorHash};
16use crate::v1::transaction::{
17 DCert, POSIXTime, ScriptContext, ScriptPurpose, TransactionHash, TransactionInfo,
18 TransactionInput, TransactionOutput, TxInInfo,
19};
20use crate::v1::value::Lovelace;
21use crate::v2::value::{AssetClass, CurrencySymbol, TokenName, Value};
22use num_bigint::BigInt;
23use proptest::collection::btree_map;
24use proptest::collection::vec;
25use proptest::option;
26use proptest::prelude::{any, prop_oneof, Just};
27use proptest::strategy::Strategy;
28use std::collections::BTreeMap;
29
30pub fn arb_ledger_bytes(length: usize) -> impl Strategy<Value = LedgerBytes> {
32 (vec(any::<u8>(), length)).prop_map(LedgerBytes)
33}
34
35pub fn arb_asset_class() -> impl Strategy<Value = AssetClass> {
39 (arb_currency_symbol(), arb_token_name()).prop_map(|(currency_symbol, token_name)| {
40 let token_name = match currency_symbol {
41 CurrencySymbol::Ada => TokenName::ada(),
42 CurrencySymbol::NativeToken(_) => token_name,
43 };
44 AssetClass {
45 currency_symbol,
46 token_name,
47 }
48 })
49}
50
51pub fn arb_currency_symbol() -> impl Strategy<Value = CurrencySymbol> {
56 prop_oneof![
57 1 =>Just(CurrencySymbol::Ada),
58 3 =>arb_minting_policy_hash().prop_map(CurrencySymbol::NativeToken)
59 ]
60}
61
62pub fn arb_token_name() -> impl Strategy<Value = TokenName> {
64 arb_ledger_bytes(32).prop_map(TokenName)
65}
66
67pub fn arb_minting_policy_hash() -> impl Strategy<Value = MintingPolicyHash> {
69 arb_script_hash().prop_map(MintingPolicyHash)
70}
71
72pub fn arb_validator_hash() -> impl Strategy<Value = ValidatorHash> {
74 arb_script_hash().prop_map(ValidatorHash)
75}
76
77pub fn arb_script_hash() -> impl Strategy<Value = ScriptHash> {
79 arb_ledger_bytes(28).prop_map(ScriptHash)
80}
81
82pub fn arb_value() -> impl Strategy<Value = Value> {
87 prop_oneof![
88 arb_native_tokens(),
89 (arb_native_tokens(), arb_natural(2)).prop_map(|(Value(outer_dict), amount)| {
90 let mut outer_dict = outer_dict.clone();
91 let inner_dict = BTreeMap::from([(TokenName::ada(), amount)]);
92 outer_dict.insert(CurrencySymbol::Ada, inner_dict);
93 Value(outer_dict)
94 })
95 ]
96}
97
98pub fn arb_native_tokens() -> impl Strategy<Value = Value> {
100 btree_map(
101 arb_minting_policy_hash().prop_map(CurrencySymbol::NativeToken),
102 btree_map(arb_token_name(), arb_natural(1), 5),
103 5,
104 )
105 .prop_map(Value)
106}
107
108pub fn arb_plutus_data() -> impl Strategy<Value = PlutusData> {
110 arb_plutus_data_leaf().prop_recursive(5, 64, 16, |arb_data| {
111 prop_oneof![
112 arb_integer().prop_map(PlutusData::Integer),
113 arb_bytes().prop_map(PlutusData::Bytes),
114 vec(arb_data.clone(), 5).prop_map(PlutusData::List),
115 vec((arb_data.clone(), arb_data.clone()), 5).prop_map(PlutusData::Map),
116 (arb_natural(1), vec(arb_data.clone(), 5))
117 .prop_map(|(id, fields)| PlutusData::Constr(id, fields)),
118 ]
119 })
120}
121
122fn arb_plutus_data_leaf() -> impl Strategy<Value = PlutusData> {
124 prop_oneof![
125 arb_integer().prop_map(PlutusData::Integer),
126 arb_bytes().prop_map(PlutusData::Bytes),
127 ]
128}
129
130pub fn arb_ed25519_pub_key_hash() -> impl Strategy<Value = Ed25519PubKeyHash> {
132 arb_ledger_bytes(28).prop_map(Ed25519PubKeyHash)
133}
134
135pub fn arb_datum_hash() -> impl Strategy<Value = DatumHash> {
137 arb_ledger_bytes(32).prop_map(DatumHash)
138}
139
140pub fn arb_datum() -> impl Strategy<Value = Datum> {
142 arb_plutus_data().prop_map(Datum)
143}
144
145pub fn arb_redeemer() -> impl Strategy<Value = Redeemer> {
147 arb_plutus_data().prop_map(Redeemer)
148}
149
150pub fn arb_redeemer_hash() -> impl Strategy<Value = RedeemerHash> {
152 arb_ledger_bytes(32).prop_map(RedeemerHash)
153}
154
155pub fn arb_extended<T>(element: T) -> impl Strategy<Value = Extended<T::Value>>
157where
158 T: Strategy,
159 T::Value: FeatureTraits + Clone,
160{
161 prop_oneof![
162 Just(Extended::NegInf),
163 Just(Extended::PosInf),
164 element.prop_map(Extended::Finite)
165 ]
166}
167
168pub fn arb_extended_posix_time() -> impl Strategy<Value = Extended<POSIXTime>> {
170 arb_extended(arb_posix_time())
171}
172
173pub fn arb_posix_time() -> impl Strategy<Value = POSIXTime> {
175 (0..2000000000).prop_map(|int| POSIXTime(BigInt::from(int)))
176}
177
178pub fn arb_upper_bound<T>(element: T) -> impl Strategy<Value = UpperBound<T::Value>>
180where
181 T: Strategy,
182 T::Value: FeatureTraits + Clone,
183{
184 (arb_extended(element), arb_bool()).prop_map(|(bound, closed)| UpperBound { bound, closed })
185}
186
187pub fn arb_lower_bound<T>(element: T) -> impl Strategy<Value = LowerBound<T::Value>>
189where
190 T: Strategy,
191 T::Value: FeatureTraits + Clone,
192{
193 (arb_extended(element), arb_bool()).prop_map(|(bound, closed)| LowerBound { bound, closed })
194}
195
196pub fn arb_interval<T>(lower_bound: T, upper_bound: T) -> impl Strategy<Value = Interval<T::Value>>
198where
199 T: Strategy,
200 T::Value: FeatureTraits + Clone,
201{
202 (lower_bound, upper_bound).prop_flat_map(|(lb, ub)| {
203 prop_oneof![
204 4 => Just(Interval::Finite(lb.clone(), ub.clone())),
205 4 => Just(Interval::StartAt(lb.clone())),
206 4 => Just(Interval::StartAfter(lb)),
207 4 => Just(Interval::EndAt(ub.clone())),
208 4 => Just(Interval::EndBefore(ub)),
209 1 => Just(Interval::Always),
210 1 => Just(Interval::Never)
211 ]
212 })
213}
214
215pub fn arb_plutus_interval<T>(
219 lower_bound: T,
220 upper_bound: T,
221) -> impl Strategy<Value = PlutusInterval<T::Value>>
222where
223 T: Strategy,
224 T::Value: FeatureTraits + Clone,
225{
226 (arb_lower_bound(lower_bound), arb_upper_bound(upper_bound))
227 .prop_map(|(from, to)| PlutusInterval { from, to })
228}
229
230pub fn arb_plutus_interval_posix_time() -> impl Strategy<Value = PlutusInterval<POSIXTime>> {
234 arb_plutus_interval(arb_posix_time(), arb_posix_time())
235}
236
237pub fn arb_interval_posix_time() -> impl Strategy<Value = Interval<POSIXTime>> {
239 (arb_posix_time(), arb_posix_time()).prop_flat_map(|(x, y)| {
240 if x > y {
241 arb_interval(Just(y), Just(x))
242 } else {
243 arb_interval(Just(x), Just(y))
244 }
245 })
246}
247
248pub fn arb_address() -> impl Strategy<Value = Address> {
250 (arb_credential(), option::of(arb_staking_credential())).prop_map(
251 |(credential, staking_credential)| Address {
252 credential,
253 staking_credential,
254 },
255 )
256}
257
258pub fn arb_chain_pointer() -> impl Strategy<Value = ChainPointer> {
260 (arb_slot(), arb_transaction_index(), arb_certificate_index()).prop_map(
261 |(slot_number, transaction_index, certificate_index)| ChainPointer {
262 slot_number,
263 transaction_index,
264 certificate_index,
265 },
266 )
267}
268
269pub fn arb_slot() -> impl Strategy<Value = Slot> {
271 arb_natural(1).prop_map(Slot)
272}
273
274pub fn arb_transaction_index() -> impl Strategy<Value = TransactionIndex> {
276 arb_natural(1).prop_map(TransactionIndex)
277}
278
279pub fn arb_certificate_index() -> impl Strategy<Value = CertificateIndex> {
281 arb_natural(1).prop_map(CertificateIndex)
282}
283
284pub fn arb_staking_credential() -> impl Strategy<Value = StakingCredential> {
286 prop_oneof![
287 arb_credential().prop_map(StakingCredential::Hash),
288 arb_chain_pointer().prop_map(StakingCredential::Pointer)
289 ]
290}
291
292pub fn arb_credential() -> impl Strategy<Value = Credential> {
294 prop_oneof![
295 arb_ed25519_pub_key_hash().prop_map(Credential::PubKey),
296 arb_validator_hash().prop_map(Credential::Script)
297 ]
298}
299
300pub fn arb_transaction_hash() -> impl Strategy<Value = TransactionHash> {
302 arb_ledger_bytes(32).prop_map(TransactionHash)
303}
304
305pub fn arb_transaction_input() -> impl Strategy<Value = TransactionInput> {
307 (arb_transaction_hash(), arb_natural(1)).prop_map(|(transaction_id, index)| TransactionInput {
308 transaction_id,
309 index,
310 })
311}
312
313pub fn arb_transaction_output() -> impl Strategy<Value = TransactionOutput> {
315 (arb_address(), arb_value(), option::of(arb_datum_hash())).prop_map(
316 |(address, value, datum_hash)| TransactionOutput {
317 address,
318 value,
319 datum_hash,
320 },
321 )
322}
323
324pub fn arb_tx_in_info() -> impl Strategy<Value = TxInInfo> {
326 (arb_transaction_input(), arb_transaction_output())
327 .prop_map(|(reference, output)| TxInInfo { reference, output })
328}
329
330pub fn arb_assoc_map<K: std::fmt::Debug, V: std::fmt::Debug>(
332 arb_k: impl Strategy<Value = K>,
333 arb_v: impl Strategy<Value = V>,
334) -> impl Strategy<Value = AssocMap<K, V>> {
335 vec((arb_k, arb_v), 10).prop_map(AssocMap)
336}
337
338pub fn arb_payment_pub_key_hash() -> impl Strategy<Value = PaymentPubKeyHash> {
340 arb_ed25519_pub_key_hash().prop_map(PaymentPubKeyHash)
341}
342
343pub fn arb_d_cert() -> impl Strategy<Value = DCert> {
345 prop_oneof![
346 arb_staking_credential().prop_map(DCert::DelegRegKey),
347 arb_staking_credential().prop_map(DCert::DelegDeRegKey),
348 (arb_staking_credential(), arb_payment_pub_key_hash())
349 .prop_map(|(sc, pkh)| DCert::DelegDelegate(sc, pkh)),
350 (arb_payment_pub_key_hash(), arb_payment_pub_key_hash())
351 .prop_map(|(p1, p2)| DCert::PoolRegister(p1, p2)),
352 (arb_payment_pub_key_hash(), arb_natural(1)).prop_map(|(pkh, i)| DCert::PoolRetire(pkh, i)),
353 Just(DCert::Genesis),
354 Just(DCert::Mir)
355 ]
356}
357
358pub fn arb_script_purpose() -> impl Strategy<Value = ScriptPurpose> {
360 prop_oneof![
361 arb_currency_symbol().prop_map(ScriptPurpose::Minting),
362 arb_transaction_input().prop_map(ScriptPurpose::Spending),
363 arb_staking_credential().prop_map(ScriptPurpose::Rewarding),
364 arb_d_cert().prop_map(ScriptPurpose::Certifying)
365 ]
366}
367
368pub fn arb_transaction_info() -> impl Strategy<Value = TransactionInfo> {
371 (
372 vec(arb_tx_in_info(), 5),
373 vec(arb_transaction_output(), 5),
374 arb_value(),
375 arb_value(),
376 vec(arb_d_cert(), 5),
377 vec((arb_staking_credential(), arb_natural(1)), 5),
378 arb_plutus_interval_posix_time(),
379 vec(arb_payment_pub_key_hash(), 5),
380 vec((arb_datum_hash(), arb_datum()), 5),
381 arb_transaction_hash(),
382 )
383 .prop_map(
384 |(inputs, outputs, fee, mint, d_cert, wdrl, valid_range, signatories, datums, id)| {
385 TransactionInfo {
386 inputs,
387 outputs,
388 fee,
389 mint,
390 d_cert,
391 wdrl,
392 valid_range,
393 signatories,
394 datums,
395 id,
396 }
397 },
398 )
399}
400
401pub fn arb_script_context() -> impl Strategy<Value = ScriptContext> {
403 (arb_script_purpose(), arb_transaction_info())
404 .prop_map(|(purpose, tx_info)| ScriptContext { purpose, tx_info })
405}
406
407pub fn arb_lovelace() -> impl Strategy<Value = Lovelace> {
408 arb_natural(1).prop_map(Lovelace)
409}
410
411pub fn arb_stake_pub_key_hash() -> impl Strategy<Value = StakePubKeyHash> {
412 arb_ed25519_pub_key_hash().prop_map(StakePubKeyHash)
413}