diff --git a/movement-sdk/types/sui-helper-types/src/block/block.rs b/movement-sdk/types/sui-helper-types/src/block/block.rs index 3a9c74a0..4b9816c0 100644 --- a/movement-sdk/types/sui-helper-types/src/block/block.rs +++ b/movement-sdk/types/sui-helper-types/src/block/block.rs @@ -1,8 +1,15 @@ +use std::collections::HashSet; + +use sui_types::base_types::ObjectID; +use sui_types::digests::SenderSignedDataDigest; +use sui_types::message_envelope::VerifiedEnvelope; use sui_types::{ transaction::SenderSignedData, executable_transaction::VerifiedExecutableTransaction }; +use sui_types::transaction::{TransactionDataAPI, TransactionData}; + /// A SuiBlock is a block as we would most often expect it to be constructed. /// It contains only user signed data. #[derive(Debug, Clone)] @@ -32,9 +39,55 @@ impl VerifiedExecutableBlock { } pub fn get_max_parallel_groups(&self) -> VerifiedExecutableExecutionGroups { - // todo: see readme - unimplemented!(); + let mut groups: Vec> = Vec::new(); + let mut objects_in_groups: Vec> = Vec::new(); + let mut processed_digests: HashSet = HashSet::new(); + for executable_transaction in self.clone().into_iter() { + let sender_signed_data = executable_transaction.clone().into_message(); + + // Skip if transaction is already processed + if processed_digests.contains(&sender_signed_data.full_message_digest()) { + continue; + } + + let TransactionData::V1(tx_data_v1) = sender_signed_data.transaction_data(); + //let shared_objects = tx_data_v1.shared_input_objects(); + let input_objects = tx_data_v1.input_objects(); + if input_objects.is_err() { + continue; + } + + let input_objects = input_objects.unwrap(); + + // Find a group where the transaction can be added without conflict + let mut group_id = 0; + while group_id < objects_in_groups.len() { + let is_conflict = input_objects.iter().any(|obj| { + objects_in_groups[group_id].contains(&(obj.object_id(), true)) && obj.is_mutable() + }); + + if !is_conflict { + break; + } + group_id += 1; + } + + // If no suitable group, create a new one + if group_id == objects_in_groups.len() { + groups.push(Vec::new()); + objects_in_groups.push(HashSet::new()); + } + + // Add the transaction to the group + for obj in input_objects { + objects_in_groups[group_id].insert((obj.object_id(), obj.is_mutable())); + } + groups[group_id].push(executable_transaction.clone()); + processed_digests.insert(sender_signed_data.full_message_digest()); + } + VerifiedExecutableExecutionGroups(groups) } + } @@ -46,4 +99,4 @@ impl IntoIterator for VerifiedExecutableBlock { fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } -} \ No newline at end of file +}