drive/util/test_helpers/test_utils/
identities.rs

1#![allow(clippy::result_large_err)] // Test helpers return drive::Error for convenience
2//! Drive Identity Helpers.
3//!
4//! This module defines helper functions pertinent to identities in Drive.
5//!
6
7use crate::drive::credit_pools::epochs::operations_factory::EpochOperations;
8use crate::drive::Drive;
9use crate::error::Error;
10use crate::util::batch::grovedb_op_batch::GroveDbOpBatchV0Methods;
11use crate::util::batch::GroveDbOpBatch;
12use dpp::block::block_info::BlockInfo;
13use dpp::block::epoch::Epoch;
14use dpp::identifier::Identifier;
15use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
16use dpp::identity::{Identity, IdentityPublicKey, IdentityV0};
17use dpp::version::PlatformVersion;
18use grovedb::TransactionArg;
19use rand::rngs::StdRng;
20use rand::{Rng, SeedableRng};
21use std::collections::BTreeMap;
22
23/// Creates a test identity from an id and inserts it into Drive.
24pub fn create_test_identity(
25    drive: &Drive,
26    id: [u8; 32],
27    seed: Option<u64>,
28    transaction: TransactionArg,
29    platform_version: &PlatformVersion,
30) -> Result<Identity, Error> {
31    let mut rng = match seed {
32        None => StdRng::from_entropy(),
33        Some(seed_value) => StdRng::seed_from_u64(seed_value),
34    };
35
36    create_test_identity_with_rng(drive, id, &mut rng, transaction, platform_version)
37}
38
39/// Creates multiple test identities with random generator and inserts them into Drive.
40///
41/// # Arguments
42///
43/// * `drive` - A reference to the Drive.
44/// * `ids` - An IntoIterator of [u8; 32] representing the ids for the test identities to create.
45/// * `rng` - A mutable reference to the random number generator.
46/// * `transaction` - A transaction argument to interact with the underlying storage.
47///
48/// # Returns
49///
50/// * `Vec<Identity>` - Returns a vector of created test identities.
51pub fn create_test_identities_with_rng<I>(
52    drive: &Drive,
53    ids: I,
54    rng: &mut StdRng,
55    transaction: TransactionArg,
56    platform_version: &PlatformVersion,
57) -> Result<Vec<Identity>, Error>
58where
59    I: IntoIterator<Item = [u8; 32]>,
60{
61    let ids_iter = ids.into_iter();
62    let mut identities = Vec::with_capacity(ids_iter.size_hint().0);
63
64    for id in ids_iter {
65        let identity =
66            create_test_identity_with_rng(drive, id, rng, transaction, platform_version)?;
67        identities.push(identity);
68    }
69
70    Ok(identities)
71}
72
73/// Creates a test identity from an id with random generator and inserts it into Drive.
74pub fn create_test_identity_with_rng(
75    drive: &Drive,
76    id: [u8; 32],
77    rng: &mut StdRng,
78    transaction: TransactionArg,
79    platform_version: &PlatformVersion,
80) -> Result<Identity, Error> {
81    let (identity_key, _) = IdentityPublicKey::random_ecdsa_master_authentication_key_with_rng(
82        1,
83        rng,
84        platform_version,
85    )?;
86
87    let mut public_keys = BTreeMap::new();
88
89    public_keys.insert(identity_key.id(), identity_key);
90
91    let identity: Identity = IdentityV0 {
92        id: Identifier::new(id),
93        revision: 0,
94        balance: 0,
95        public_keys,
96    }
97    .into();
98
99    drive
100        .add_new_identity(
101            identity.clone(),
102            false,
103            &BlockInfo::default(),
104            true,
105            transaction,
106            platform_version,
107        )
108        .expect("should insert identity");
109
110    Ok(identity)
111}
112
113/// Increments each proposer in the list given's block count by 1.
114pub fn increment_in_epoch_each_proposers_block_count(
115    drive: &Drive,
116    epoch_tree: &Epoch,
117    proposers: &Vec<[u8; 32]>,
118    transaction: TransactionArg,
119    platform_version: &PlatformVersion,
120) {
121    let mut batch = GroveDbOpBatch::new();
122
123    for proposer_pro_tx_hash in proposers {
124        let op = epoch_tree
125            .increment_proposer_block_count_operation(
126                drive,
127                proposer_pro_tx_hash,
128                None,
129                transaction,
130                platform_version,
131            )
132            .expect("should increment proposer block count");
133        batch.push(op);
134    }
135
136    drive
137        .grove_apply_batch(batch, true, transaction, &platform_version.drive)
138        .expect("should apply batch");
139}
140
141/// Creates test masternode identities and adds them as epoch block proposers.
142pub fn create_test_masternode_identities_and_add_them_as_epoch_block_proposers(
143    drive: &Drive,
144    epoch: &Epoch,
145    count: u16,
146    seed: Option<u64>,
147    transaction: TransactionArg,
148    platform_version: &PlatformVersion,
149) -> Vec<[u8; 32]> {
150    let proposers =
151        create_test_masternode_identities(drive, count, seed, transaction, platform_version);
152
153    increment_in_epoch_each_proposers_block_count(
154        drive,
155        epoch,
156        &proposers,
157        transaction,
158        platform_version,
159    );
160
161    proposers
162}
163
164/// Creates a list of test Masternode identities of size `count` with random data
165pub fn create_test_masternode_identities(
166    drive: &Drive,
167    count: u16,
168    seed: Option<u64>,
169    transaction: TransactionArg,
170    platform_version: &PlatformVersion,
171) -> Vec<[u8; 32]> {
172    let mut rng = match seed {
173        None => StdRng::from_entropy(),
174        Some(seed_value) => StdRng::seed_from_u64(seed_value),
175    };
176    create_test_masternode_identities_with_rng(
177        drive,
178        count,
179        &mut rng,
180        transaction,
181        platform_version,
182    )
183}
184
185/// Creates a list of test Masternode identities of size `count` with random data
186pub fn create_test_masternode_identities_with_rng(
187    drive: &Drive,
188    count: u16,
189    rng: &mut StdRng,
190    transaction: TransactionArg,
191    platform_version: &PlatformVersion,
192) -> Vec<[u8; 32]> {
193    let mut identity_ids: Vec<[u8; 32]> = Vec::with_capacity(count as usize);
194
195    for _ in 0..count {
196        let proposer_pro_tx_hash = rng.gen::<[u8; 32]>();
197        create_test_identity_with_rng(
198            drive,
199            proposer_pro_tx_hash,
200            rng,
201            transaction,
202            platform_version,
203        )
204        .expect("expected to get a platform version");
205
206        identity_ids.push(proposer_pro_tx_hash);
207    }
208
209    identity_ids
210}
211
212/// Creates a list of test Masternode identities of size `count` with random data
213pub fn generate_pro_tx_hashes(count: u16, rng: &mut StdRng) -> Vec<[u8; 32]> {
214    let mut identity_ids: Vec<[u8; 32]> = Vec::with_capacity(count as usize);
215
216    for _ in 0..count {
217        let proposer_pro_tx_hash = rng.gen::<[u8; 32]>();
218        identity_ids.push(proposer_pro_tx_hash);
219    }
220
221    identity_ids
222}