plutus_ledger_api/generators/correct/
v3.rs

1//! Proptest strategies for Plutus V3 types
2//!
3//! These strategies always return valid values.
4
5use proptest::{
6    collection::vec,
7    option,
8    prelude::{Just, Strategy},
9    prop_oneof,
10};
11
12use crate::{
13    generators::correct::{
14        primitive::arb_integer,
15        v1::{
16            arb_currency_symbol, arb_datum, arb_ed25519_pub_key_hash, arb_lovelace,
17            arb_payment_pub_key_hash, arb_stake_pub_key_hash,
18        },
19    },
20    v3::{
21        ratio::Rational,
22        transaction::{
23            ChangedParameters, ColdCommitteeCredential, Committee, Constitution, DRep,
24            DRepCredential, Delegatee, GovernanceAction, GovernanceActionId,
25            HotCommitteeCredential, ProposalProcedure, ProtocolVersion, ScriptContext, ScriptInfo,
26            ScriptPurpose, TransactionHash, TransactionInfo, TransactionInput, TxCert, TxInInfo,
27            Vote, Voter,
28        },
29    },
30};
31
32use super::{
33    primitive::arb_natural,
34    v1::{
35        arb_assoc_map, arb_credential, arb_datum_hash, arb_ledger_bytes, arb_plutus_data,
36        arb_plutus_interval_posix_time, arb_redeemer, arb_script_hash, arb_value,
37    },
38    v2::arb_transaction_output,
39};
40
41/// Strategy to generate a transaction hash
42pub fn arb_transaction_hash() -> impl Strategy<Value = TransactionHash> {
43    arb_ledger_bytes(32).prop_map(TransactionHash)
44}
45
46/// Strategy to generate a transaction input
47pub fn arb_transaction_input() -> impl Strategy<Value = TransactionInput> {
48    (arb_transaction_hash(), arb_natural(1)).prop_map(|(transaction_id, index)| TransactionInput {
49        transaction_id,
50        index,
51    })
52}
53
54/// Strategy to generate cold committee credentials
55pub fn arb_cold_committee_credential() -> impl Strategy<Value = ColdCommitteeCredential> {
56    arb_credential().prop_map(ColdCommitteeCredential)
57}
58
59/// Strategy to generate hot committee credentials
60pub fn arb_hot_committee_credential() -> impl Strategy<Value = HotCommitteeCredential> {
61    arb_credential().prop_map(HotCommitteeCredential)
62}
63
64/// Strategy to generate DRep credentials
65pub fn arb_d_rep_credential() -> impl Strategy<Value = DRepCredential> {
66    arb_credential().prop_map(DRepCredential)
67}
68
69/// Strategy to generate DReps
70pub fn arb_d_rep() -> impl Strategy<Value = DRep> {
71    prop_oneof![
72        arb_d_rep_credential().prop_map(DRep::DRep),
73        Just(DRep::AlwaysAbstain),
74        Just(DRep::AlwaysNoConfidence)
75    ]
76}
77
78/// Strategy to generate delegatees
79pub fn arb_delegatee() -> impl Strategy<Value = Delegatee> {
80    prop_oneof![
81        arb_stake_pub_key_hash().prop_map(Delegatee::Stake),
82        arb_d_rep().prop_map(Delegatee::Vote),
83        (arb_stake_pub_key_hash(), arb_d_rep()).prop_map(|(h, r)| Delegatee::StakeVote(h, r))
84    ]
85}
86
87/// Strategy to generate tx certs
88pub fn arb_tx_cert() -> impl Strategy<Value = TxCert> {
89    prop_oneof![
90        (arb_credential(), option::of(arb_lovelace())).prop_map(|(c, l)| TxCert::RegStaking(c, l)),
91        (arb_credential(), option::of(arb_lovelace()))
92            .prop_map(|(c, l)| TxCert::UnRegStaking(c, l)),
93        (arb_credential(), arb_delegatee()).prop_map(|(c, d)| TxCert::DelegStaking(c, d)),
94        (arb_credential(), arb_delegatee(), arb_lovelace())
95            .prop_map(|(c, d, l)| TxCert::RegDeleg(c, d, l)),
96        (arb_d_rep_credential(), arb_lovelace()).prop_map(|(d, l)| TxCert::RegDRep(d, l)),
97        arb_d_rep_credential().prop_map(TxCert::UpdateDRep),
98        (arb_d_rep_credential(), arb_lovelace()).prop_map(|(d, l)| TxCert::UnRegDRep(d, l)),
99        (arb_ed25519_pub_key_hash(), arb_ed25519_pub_key_hash())
100            .prop_map(|(pkh1, pkh2)| TxCert::PoolRegister(pkh1, pkh2)),
101        (arb_ed25519_pub_key_hash(), arb_integer()).prop_map(|(pkh, i)| TxCert::PoolRetire(pkh, i)),
102        (
103            arb_cold_committee_credential(),
104            arb_hot_committee_credential()
105        )
106            .prop_map(|(c, h)| TxCert::AuthHotCommittee(c, h)),
107        arb_cold_committee_credential().prop_map(TxCert::ResignColdCommittee)
108    ]
109}
110
111/// Strategy to generate voters
112pub fn arb_voter() -> impl Strategy<Value = Voter> {
113    prop_oneof![
114        arb_hot_committee_credential().prop_map(Voter::CommitteeVoter),
115        arb_d_rep_credential().prop_map(Voter::DRepVoter),
116        arb_ed25519_pub_key_hash().prop_map(Voter::StakePoolVoter)
117    ]
118}
119
120/// Strategy to generate votes
121pub fn arb_vote() -> impl Strategy<Value = Vote> {
122    prop_oneof![Just(Vote::VoteNo), Just(Vote::VoteYes), Just(Vote::Abstain)]
123}
124
125/// Strategy to generate governance action ids
126pub fn arb_governance_action_id() -> impl Strategy<Value = GovernanceActionId> {
127    (arb_transaction_hash(), arb_integer()).prop_map(|(tx_id, gov_action_id)| GovernanceActionId {
128        tx_id,
129        gov_action_id,
130    })
131}
132
133/// Strategy to generate committees
134pub fn arb_committee() -> impl Strategy<Value = Committee> {
135    (
136        arb_assoc_map(arb_cold_committee_credential(), arb_integer()),
137        arb_rational(),
138    )
139        .prop_map(|(members, quorum)| Committee { members, quorum })
140}
141
142/// Strategy to generate rationals
143pub fn arb_rational() -> impl Strategy<Value = Rational> {
144    (arb_integer(), arb_integer()).prop_map(|(n, d)| Rational(n, d))
145}
146
147/// Strategy to generate constitutions
148pub fn arb_constitution() -> impl Strategy<Value = Constitution> {
149    option::of(arb_script_hash()).prop_map(|constitution_script| Constitution {
150        constitution_script,
151    })
152}
153
154/// Strategy to generate protocol versions
155pub fn arb_protocol_version() -> impl Strategy<Value = ProtocolVersion> {
156    (arb_natural(1), arb_natural(1)).prop_map(|(major, minor)| ProtocolVersion { major, minor })
157}
158
159/// Strategy to generate change parameters
160pub fn arb_changed_parameters() -> impl Strategy<Value = ChangedParameters> {
161    arb_plutus_data().prop_map(ChangedParameters)
162}
163
164/// Strategy to generate governance actions
165pub fn arb_governance_action() -> impl Strategy<Value = GovernanceAction> {
166    prop_oneof![
167        (
168            option::of(arb_governance_action_id()),
169            arb_changed_parameters(),
170            option::of(arb_script_hash())
171        )
172            .prop_map(|(g, c, s)| GovernanceAction::ParameterChange(g, c, s)),
173        (
174            option::of(arb_governance_action_id()),
175            arb_protocol_version()
176        )
177            .prop_map(|(g, p)| GovernanceAction::HardForkInitiation(g, p)),
178        (
179            arb_assoc_map(arb_credential(), arb_lovelace()),
180            option::of(arb_script_hash())
181        )
182            .prop_map(|(a, s)| GovernanceAction::TreasuryWithdrawals(a, s)),
183        option::of(arb_governance_action_id()).prop_map(GovernanceAction::NoConfidence),
184        (
185            option::of(arb_governance_action_id()),
186            vec(arb_cold_committee_credential(), 5),
187            arb_assoc_map(arb_cold_committee_credential(), arb_integer()),
188            arb_rational()
189        )
190            .prop_map(|(g, c, cm, q)| GovernanceAction::UpdateCommittee(g, c, cm, q)),
191        (option::of(arb_governance_action_id()), arb_constitution())
192            .prop_map(|(g, c)| GovernanceAction::NewConstitution(g, c)),
193        Just(GovernanceAction::InfoAction)
194    ]
195}
196
197/// Strategy to generate protocol procedures
198pub fn arb_proposal_procedure() -> impl Strategy<Value = ProposalProcedure> {
199    (arb_lovelace(), arb_credential(), arb_governance_action()).prop_map(|(l, c, g)| {
200        ProposalProcedure {
201            deposit: l,
202            return_addr: c,
203            governance_action: g,
204        }
205    })
206}
207
208/// Strategy to generate script purposes
209pub fn arb_script_purpose() -> impl Strategy<Value = ScriptPurpose> {
210    prop_oneof![
211        arb_currency_symbol().prop_map(ScriptPurpose::Minting),
212        arb_transaction_input().prop_map(ScriptPurpose::Spending),
213        arb_credential().prop_map(ScriptPurpose::Rewarding),
214        (arb_integer(), arb_tx_cert()).prop_map(|(i, c)| ScriptPurpose::Certifying(i, c)),
215        arb_voter().prop_map(ScriptPurpose::Voting),
216        (arb_integer(), arb_proposal_procedure()).prop_map(|(i, p)| ScriptPurpose::Proposing(i, p))
217    ]
218}
219
220/// Strategy to generate script info
221pub fn arb_script_info() -> impl Strategy<Value = ScriptInfo> {
222    prop_oneof![
223        arb_currency_symbol().prop_map(ScriptInfo::Minting),
224        (arb_transaction_input(), option::of(arb_datum()))
225            .prop_map(|(i, d)| ScriptInfo::Spending(i, d)),
226        arb_credential().prop_map(ScriptInfo::Rewarding),
227        (arb_integer(), arb_tx_cert()).prop_map(|(i, c)| ScriptInfo::Certifying(i, c)),
228        arb_voter().prop_map(ScriptInfo::Voting),
229        (arb_integer(), arb_proposal_procedure()).prop_map(|(i, p)| ScriptInfo::Proposing(i, p))
230    ]
231}
232
233/// Strategy to generate transaction info
234pub fn arb_transaction_info() -> impl Strategy<Value = TransactionInfo> {
235    (
236        vec(arb_tx_in_info(), 5),
237        vec(arb_tx_in_info(), 5),
238        vec(arb_transaction_output(), 5),
239        arb_lovelace(),
240        arb_value(),
241        vec(arb_tx_cert(), 5),
242        arb_assoc_map(arb_credential(), arb_lovelace()),
243        arb_plutus_interval_posix_time(),
244        vec(arb_payment_pub_key_hash(), 5),
245        arb_assoc_map(arb_script_purpose(), arb_redeemer()),
246        arb_assoc_map(arb_datum_hash(), arb_datum()),
247        // HACK(chfanghr): Strategy is not implemented for longer tuples
248        (
249            arb_transaction_hash(),
250            arb_assoc_map(
251                arb_voter(),
252                arb_assoc_map(arb_governance_action_id(), arb_vote()),
253            ),
254            vec(arb_proposal_procedure(), 5),
255            option::of(arb_lovelace()),
256            option::of(arb_lovelace()),
257        ),
258    )
259        .prop_map(
260            |(
261                inputs,
262                reference_inputs,
263                outputs,
264                fee,
265                mint,
266                tx_certs,
267                wdrl,
268                valid_range,
269                signatories,
270                redeemers,
271                datums,
272                (id, votes, proposal_procedures, current_treasury_amount, treasury_donation),
273            )| {
274                TransactionInfo {
275                    inputs,
276                    reference_inputs,
277                    outputs,
278                    fee,
279                    mint,
280                    tx_certs,
281                    wdrl,
282                    valid_range,
283                    signatories,
284                    redeemers,
285                    datums,
286                    id,
287                    votes,
288                    proposal_procedures,
289                    current_treasury_amount,
290                    treasury_donation,
291                }
292            },
293        )
294}
295
296/// Strategy to generate a TxInInfo
297pub fn arb_tx_in_info() -> impl Strategy<Value = TxInInfo> {
298    (arb_transaction_input(), arb_transaction_output())
299        .prop_map(|(reference, output)| TxInInfo { reference, output })
300}
301
302/// Strategy to generate script contexts
303pub fn arb_script_context() -> impl Strategy<Value = ScriptContext> {
304    (arb_transaction_info(), arb_redeemer(), arb_script_info()).prop_map(
305        |(tx_info, redeemer, script_info)| ScriptContext {
306            tx_info,
307            redeemer,
308            script_info,
309        },
310    )
311}