bee_block/rand/output/
mod.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4/// Module providing random feature generation utilities.
5pub mod feature;
6/// Module providing random unlock condition generation utilities.
7pub mod unlock_condition;
8
9use primitive_types::U256;
10
11use crate::{
12    output::{
13        unlock_condition::ImmutableAliasAddressUnlockCondition, AliasId, AliasOutput, BasicOutput, FoundryOutput,
14        InputsCommitment, NftId, NftOutput, Output, OutputId, SimpleTokenScheme, TokenScheme, TreasuryOutput,
15        OUTPUT_INDEX_RANGE,
16    },
17    rand::{
18        address::rand_alias_address,
19        bytes::rand_bytes_array,
20        number::{rand_number, rand_number_range},
21        output::{
22            feature::rand_allowed_features,
23            unlock_condition::{
24                rand_address_unlock_condition, rand_address_unlock_condition_different_from,
25                rand_governor_address_unlock_condition_different_from,
26                rand_state_controller_address_unlock_condition_different_from,
27            },
28        },
29        transaction::rand_transaction_id,
30    },
31};
32
33/// Generates a random [`OutputId`].
34pub fn rand_output_id() -> OutputId {
35    OutputId::new(rand_transaction_id(), rand_number_range(OUTPUT_INDEX_RANGE)).unwrap()
36}
37
38/// Generates a random treasury output.
39pub fn rand_treasury_output(token_supply: u64) -> TreasuryOutput {
40    TreasuryOutput::new(rand_number_range(0..token_supply), token_supply).unwrap()
41}
42
43/// Generates a random [`BasicOutput`](BasicOutput).
44pub fn rand_basic_output(token_supply: u64) -> BasicOutput {
45    let features = rand_allowed_features(BasicOutput::ALLOWED_FEATURES);
46    // TODO: Add `NativeTokens`
47    BasicOutput::build_with_amount(rand_number_range(Output::AMOUNT_MIN..token_supply))
48        .unwrap()
49        .with_features(features)
50        .add_unlock_condition(rand_address_unlock_condition().into())
51        .finish(token_supply)
52        .unwrap()
53}
54
55/// Generates a random [`AliasId`](AliasId).
56pub fn rand_alias_id() -> AliasId {
57    AliasId::from(rand_bytes_array())
58}
59
60/// Generates a random [`AliasOutput`](AliasOutput).
61pub fn rand_alias_output(token_supply: u64) -> AliasOutput {
62    let features = rand_allowed_features(AliasOutput::ALLOWED_FEATURES);
63
64    // We need to make sure that `AliasId` and `Address` don't match.
65    let alias_id = rand_alias_id();
66
67    AliasOutput::build_with_amount(rand_number_range(Output::AMOUNT_MIN..token_supply), alias_id)
68        .unwrap()
69        .with_features(features)
70        .add_unlock_condition(rand_state_controller_address_unlock_condition_different_from(&alias_id).into())
71        .add_unlock_condition(rand_governor_address_unlock_condition_different_from(&alias_id).into())
72        .finish(token_supply)
73        .unwrap()
74}
75
76/// Generates a random [`TokenScheme`].
77pub fn rand_token_scheme() -> TokenScheme {
78    let max = U256::from(rand_bytes_array()).saturating_add(U256::one());
79    let minted = U256::from(rand_bytes_array()) % max.saturating_add(U256::one());
80    let melted = U256::from(rand_bytes_array()) % minted.saturating_add(U256::one());
81
82    TokenScheme::Simple(SimpleTokenScheme::new(minted, melted, max).unwrap())
83}
84
85/// Generates a random [`FoundryOutput`](FoundryOutput).
86pub fn rand_foundry_output(token_supply: u64) -> FoundryOutput {
87    let features = rand_allowed_features(FoundryOutput::ALLOWED_FEATURES);
88
89    FoundryOutput::build_with_amount(
90        rand_number_range(Output::AMOUNT_MIN..token_supply),
91        rand_number(),
92        rand_token_scheme(),
93    )
94    .unwrap()
95    .with_features(features)
96    .add_unlock_condition(ImmutableAliasAddressUnlockCondition::new(rand_alias_address()).into())
97    .finish(token_supply)
98    .unwrap()
99}
100
101/// Generates a random [`NftOutput`](NftOutput).
102pub fn rand_nft_output(token_supply: u64) -> NftOutput {
103    let features = rand_allowed_features(NftOutput::ALLOWED_FEATURES);
104
105    // We need to make sure that `NftId` and `Address` don't match.
106    let nft_id = NftId::from(rand_bytes_array());
107
108    NftOutput::build_with_amount(rand_number_range(Output::AMOUNT_MIN..token_supply), nft_id)
109        .unwrap()
110        .with_features(features)
111        .add_unlock_condition(rand_address_unlock_condition_different_from(&nft_id).into())
112        .finish(token_supply)
113        .unwrap()
114}
115
116/// Generates a random [`InputsCommitment`].
117pub fn rand_inputs_commitment() -> InputsCommitment {
118    InputsCommitment::from(rand_bytes_array())
119}
120
121/// Generates a random [`Output`].
122pub fn rand_output(token_supply: u64) -> Output {
123    match rand_number::<u64>() % 5 {
124        0 => rand_treasury_output(token_supply).into(),
125        1 => rand_basic_output(token_supply).into(),
126        2 => rand_alias_output(token_supply).into(),
127        3 => rand_foundry_output(token_supply).into(),
128        4 => rand_nft_output(token_supply).into(),
129        _ => unreachable!(),
130    }
131}