diff --git a/c-pallets/file-bank/src/functions.rs b/c-pallets/file-bank/src/functions.rs index c1ae4ec6..cd89358c 100644 --- a/c-pallets/file-bank/src/functions.rs +++ b/c-pallets/file-bank/src/functions.rs @@ -17,7 +17,6 @@ impl Pallet { file_hash: &Hash, deal_info: BoundedVec, T::SegmentCount>, mut miner_task_list: BoundedVec, ConstU32>, - share_info: Vec>, user_brief: UserBrief, stat: FileState, file_size: u128, @@ -29,48 +28,26 @@ impl Pallet { fragment_list: Default::default(), }; - let mut mark_miner: Vec> = Default::default(); - - let mut flag = true; - for share_segment_info in &share_info { - if segment.hash == share_segment_info.hash { - segment_info.fragment_list = share_segment_info.fragment_list.clone(); - flag = false; - break; - } + for miner_task in &mut miner_task_list { + miner_task.fragment_list.sort(); } - if flag { + for frag_hash in segment.fragment_list.iter() { for miner_task in &mut miner_task_list { - miner_task.fragment_list.sort(); - } - - let best_count: u32 = (SEGMENT_SIZE * 15 / 10 / FRAGMENT_SIZE) as u32; - let cur_count: u32 = miner_task_list.len() as u32; - let flag = best_count == cur_count; - - for frag_hash in segment.fragment_list.iter() { - for miner_task in &mut miner_task_list { - if flag { - if mark_miner.contains(&miner_task.miner) { - continue; - } - } - if let Ok(index) = miner_task.fragment_list.binary_search(&frag_hash) { - let frag_info = FragmentInfo:: { - hash: *frag_hash, - avail: true, - miner: miner_task.miner.clone(), - }; - segment_info.fragment_list.try_push(frag_info).map_err(|_e| Error::::BoundedVecError)?; - miner_task.fragment_list.remove(index); - mark_miner.push(miner_task.miner.clone()); - break; - } + if let Ok(index) = miner_task.fragment_list.binary_search(&frag_hash) { + let miner = miner_task.miner.clone().ok_or(Error::::Unexpected)?; + let frag_info = FragmentInfo:: { + hash: *frag_hash, + avail: true, + miner: miner.clone(), + }; + segment_info.fragment_list.try_push(frag_info).map_err(|_e| Error::::BoundedVecError)?; + miner_task.fragment_list.remove(index); + break; } } } - + segment_info_list.try_push(segment_info).map_err(|_e| Error::::BoundedVecError)?; } @@ -134,11 +111,10 @@ impl Pallet { pub(super) fn generate_deal( file_hash: Hash, file_info: BoundedVec, T::SegmentCount>, + miner_task_list: BoundedVec, ConstU32>, user_brief: UserBrief, file_size: u128, ) -> DispatchResult { - let miner_task_list = Self::random_assign_miner(&file_info)?; - let space = Self::cal_file_size(file_info.len() as u128); let life = space / TRANSFER_RATE + 1; @@ -150,10 +126,8 @@ impl Pallet { count: 0, file_size, segment_list: file_info.clone(), - needed_list: file_info, user: user_brief, - assigned_miner: miner_task_list, - share_info: Default::default(), + miner_task_list: miner_task_list, complete_list: Default::default(), }; @@ -176,7 +150,7 @@ impl Pallet { Option::None, schedule::HARD_DEADLINE, frame_system::RawOrigin::Root.into(), - Call::deal_reassign_miner{deal_hash: deal_hash, count: count, life: life}.into(), + Call::deal_timing_task{deal_hash: deal_hash, count: count, life: life}.into(), ).map_err(|_| Error::::Unexpected)?; Ok(()) @@ -205,9 +179,11 @@ impl Pallet { let needed_space = Self::cal_file_size(deal_info.segment_list.len() as u128); T::StorageHandle::unlock_user_space(&deal_info.user.user, needed_space)?; // unlock mienr space - for miner_task in deal_info.assigned_miner { - let count = miner_task.fragment_list.len() as u128; - T::MinerControl::unlock_space(&miner_task.miner, FRAGMENT_SIZE * count)?; + for miner_task in deal_info.miner_task_list { + if let Some(miner) = miner_task.miner { + let count = miner_task.fragment_list.len() as u128; + T::MinerControl::unlock_space(&miner, FRAGMENT_SIZE * count)?; + } } >::remove(deal_hash); @@ -215,168 +191,6 @@ impl Pallet { Ok(()) } - pub(super) fn reassign_miner( - task_list: BoundedVec, T::FragmentCount>, - selected_miner: BoundedVec, T::FragmentCount>, - ) -> Result, T::FragmentCount>, DispatchError> { - let mut all_miner = T::MinerControl::get_all_miner()?; - let mut total = all_miner.len() as u32; - let mut seed = >::block_number().saturated_into(); - // Used to calculate the upper limit of the number of random selections - let random_count_limit = task_list.len() as u32 * 10 + 10; - let mut new_task_list: BoundedVec, T::FragmentCount> = Default::default(); - for miner_task in &task_list { - // Used to count the number of random selections. - let mut cur_count = 0; - let miner = loop { - if random_count_limit == cur_count { - Err(Error::::NotQualified)?; - } - - if total == 0 { - Err(Error::::NotQualified)?; - } - - let index = Self::generate_random_number(seed)? as usize % all_miner.len(); - seed = seed.checked_add(1).ok_or(Error::::Overflow)?; - - let miner = all_miner[index as usize].clone(); - all_miner.remove(index as usize); - cur_count += 1; - total = total - 1; - - if selected_miner.contains(&miner) { - continue; - } - - if Self::miner_failed_exceeds_limit(&miner) { - continue; - } - - let result = T::MinerControl::is_positive(&miner)?; - if !result { - continue; - } - - let (idle, _) = T::MinerControl::get_power(&miner)?; - let needed_size = miner_task.fragment_list.len() as u128 * FRAGMENT_SIZE; - if idle < needed_size { - continue; - } - T::MinerControl::lock_space(&miner, miner_task.fragment_list.len() as u128 * FRAGMENT_SIZE)?; - - break miner; - }; - - new_task_list.try_push(MinerTaskList::{miner: miner, fragment_list: miner_task.fragment_list.clone()}).map_err(|_| Error::::BugInvalid)?; - } - - return Ok(new_task_list) - } - - pub(super) fn random_assign_miner( - needed_list: &BoundedVec, T::SegmentCount> - ) -> Result, ConstU32>, DispatchError> { - let mut miner_task_list: BoundedVec, ConstU32> = Default::default(); - let mut miner_idle_space_list: Vec = Default::default(); - // The optimal number of miners required for storage. - // segment_size * 1.5 / fragment_size. - let miner_count: u32 = (SEGMENT_SIZE * 15 / 10 / FRAGMENT_SIZE) as u32; - let mut seed = >::block_number().saturated_into(); - - let mut all_miner = T::MinerControl::get_all_miner()?; - let mut total = all_miner.len() as u32; - - // ensure!(total > miner_count, Error::::NodesInsufficient); - let max_count = miner_count * 5; - let mut cur_count = 0; - let mut total_idle_space = 0; - - // start random choose miner - loop { - // Get a random subscript. - if total == 0 { - break; - } - - let index = Self::generate_random_number(seed)? as u32 % total; - // seed + 1 - seed = seed.checked_add(1).ok_or(Error::::Overflow)?; - - // When the number of cycles reaches the upper limit, the cycle ends. - if cur_count == max_count { - break; - } - - // Number of cycles plus 1 - cur_count += 1; - - // Judge whether the idle space of the miners is sufficient. - let miner = all_miner[index as usize].clone(); - all_miner.remove(index as usize); - total = total - 1; - - if Self::miner_failed_exceeds_limit(&miner) { - continue; - } - let result = T::MinerControl::is_positive(&miner)?; - if !result { - log::info!("Isn't positive"); - continue; - } - - let cur_space: u128 = T::MinerControl::get_miner_idle_space(&miner)?; - // If sufficient, the miner is selected. - if cur_space > needed_list.len() as u128 * FRAGMENT_SIZE { - // Accumulate all idle space of currently selected miners - total_idle_space = total_idle_space.checked_add(&cur_space).ok_or(Error::::Overflow)?; - let miner_task = MinerTaskList::{ - miner: miner, - fragment_list: Default::default(), - }; - miner_task_list.try_push(miner_task).map_err(|_e| Error::::BoundedVecError)?; - miner_idle_space_list.push(cur_space); - } - // If the selected number of miners has reached the optimal number, the cycle ends. - if miner_task_list.len() as u32 == miner_count { - break; - } - } - - ensure!(miner_task_list.len() != 0, Error::::BugInvalid); - ensure!(total_idle_space > SEGMENT_SIZE * 15 / 10, Error::::NodesInsufficient); - - // According to the selected miner. - // Assign responsible documents to miners. - for segment_list in needed_list { - let mut index = 0; - for hash in &segment_list.fragment_list { - // To prevent the number of miners from not meeting the fragment number. - // It may occur that one miner stores multiple fragments - loop { - // Obtain the account of the storage node through the subscript. - // To prevent exceeding the boundary, use '%'. - let temp_index = index % miner_task_list.len(); - let cur_space = miner_idle_space_list[temp_index]; - // To prevent a miner from storing multiple fragments, - // the idle space is insufficient - if cur_space > (miner_task_list[temp_index].fragment_list.len() as u128 + 1) * FRAGMENT_SIZE { - miner_task_list[temp_index].fragment_list.try_push(*hash).map_err(|_e| Error::::BoundedVecError)?; - break; - } - index = index.checked_add(1).ok_or(Error::::PanicOverflow)?; - } - index = index.checked_add(1).ok_or(Error::::PanicOverflow)?; - } - } - // lock miner space - for miner_task in miner_task_list.iter() { - T::MinerControl::lock_space(&miner_task.miner, miner_task.fragment_list.len() as u128 * FRAGMENT_SIZE)?; - } - - Ok(miner_task_list) - } - pub(super) fn cal_file_size(len: u128) -> u128 { len * (SEGMENT_SIZE * 15 / 10) } @@ -650,26 +464,6 @@ impl Pallet { true } - pub(super) fn add_task_failed_count(miner: &AccountOf) -> DispatchResult { - TaskFailedCount::::try_mutate(miner, |count| -> DispatchResult { - *count = count.checked_add(1).unwrap_or(255); - Ok(()) - }) - } - - pub(super) fn zero_task_failed_count(miner: &AccountOf) -> DispatchResult { - TaskFailedCount::::try_mutate(miner, |count| -> DispatchResult { - *count = 0; - Ok(()) - }) - } - - pub(super) fn miner_failed_exceeds_limit(miner: &AccountOf) -> bool { - let count = TaskFailedCount::::get(miner); - - count >= 5 - } - pub(super) fn get_segment_length_from_deal(deal_hash: &Hash) -> u32 { if let Ok(deal) = >::try_get(deal_hash) { return deal.segment_list.len() as u32; diff --git a/c-pallets/file-bank/src/lib.rs b/c-pallets/file-bank/src/lib.rs index b5d534e7..980a141c 100755 --- a/c-pallets/file-bank/src/lib.rs +++ b/c-pallets/file-bank/src/lib.rs @@ -423,6 +423,10 @@ pub mod pallet { origin: OriginFor, file_hash: Hash, deal_info: BoundedVec, T::SegmentCount>, + assigned_data: BoundedVec< + BoundedVec, + ConstU32, + >, user_brief: UserBrief, file_size: u128, ) -> DispatchResult { @@ -460,9 +464,22 @@ pub mod pallet { Ok(()) })?; } else { + ensure!(assigned_data.len() as u32 == ASSIGN_MINER_IDEAL_QUANTITY, Error::::SpecError); + let mut miner_task_list: BoundedVec, ConstU32> = Default::default(); + let mut index = 1; + for fragment_list in assigned_data { + ensure!(fragment_list.len() == deal_info.len(), Error::::SpecError); + let miner_task = MinerTaskList:: { + index, + miner: None, + fragment_list, + }; + miner_task_list.try_push(miner_task).map_err(|_| Error::::BoundedVecError)?; + index += 1; + } T::StorageHandle::lock_user_space(&user_brief.user, needed_space)?; // TODO! Replace the file_hash param - Self::generate_deal(file_hash.clone(), deal_info, user_brief.clone(), file_size)?; + Self::generate_deal(file_hash.clone(), deal_info, miner_task_list, user_brief.clone(), file_size)?; } Self::deposit_event(Event::::UploadDeclaration { operator: sender, owner: user_brief.user, deal_hash: file_hash }); @@ -488,41 +505,18 @@ pub mod pallet { let v = Pallet::::get_segment_length_from_deal(&deal_hash); ::WeightInfo::deal_reassign_miner(v) })] - pub fn deal_reassign_miner( + pub fn deal_timing_task( origin: OriginFor, deal_hash: Hash, count: u8, life: u32, ) -> DispatchResult { let _ = ensure_root(origin)?; - // ReadME - let _segment_length = Self::get_segment_length_from_deal(&deal_hash); - if count < 20 { - if let Err(_e) = >::try_mutate(&deal_hash, |opt| -> DispatchResult { - let deal_info = opt.as_mut().ok_or(Error::::NonExistent)?; - // unlock miner space - let mut needed_list: BoundedVec, T::FragmentCount> = Default::default(); - let mut selected_miner: BoundedVec, T::FragmentCount> = Default::default(); - for miner_task in &deal_info.assigned_miner.clone() { - if !deal_info.complete_list.contains(&miner_task.miner) { - needed_list.try_push(miner_task.clone()).map_err(|_| Error::::Overflow)?; - } - selected_miner.try_push(miner_task.miner.clone()).map_err(|_| Error::::Overflow)?; - } - let mut miner_task_list = Self::reassign_miner(needed_list.clone(), selected_miner.clone())?.to_vec(); - for miner_task in &deal_info.assigned_miner.clone() { - if !deal_info.complete_list.contains(&miner_task.miner) { - deal_info.assigned_miner.retain(|temp_info| temp_info.miner != miner_task.miner); - let task_count = miner_task.fragment_list.len() as u128; - let unlock_space = FRAGMENT_SIZE.checked_mul(task_count).ok_or(Error::::Overflow)?; - T::MinerControl::unlock_space(&miner_task.miner, unlock_space)?; - Self::add_task_failed_count(&miner_task.miner)?; - } - } - deal_info.assigned_miner.try_append(&mut miner_task_list).map_err(|_| Error::::Overflow)?; + if count < 2 { + if let Err(_e) = >::try_mutate(&deal_hash, |deal_opt| -> DispatchResult { + let deal_info = deal_opt.as_mut().ok_or(Error::::NonExistent)?; deal_info.count = count; - // count <= 20 Self::start_first_task(deal_hash.0.to_vec(), deal_hash, count + 1, life)?; Ok(()) }) { @@ -614,36 +608,52 @@ pub mod pallet { #[pallet::weight(::WeightInfo::transfer_report(Pallet::::get_segment_length_from_deal(&deal_hash)))] pub fn transfer_report( origin: OriginFor, + index: u8, deal_hash: Hash, ) -> DispatchResult { let sender = ensure_signed(origin)?; ensure!(>::contains_key(&deal_hash), Error::::NonExistent); + ensure!(index as u32 <= FRAGMENT_COUNT, Error::::SpecError); + ensure!(index > 0, Error::::SpecError); >::try_mutate(&deal_hash, |deal_info_opt| -> DispatchResult { // can use unwrap because there was a judgment above let deal_info = deal_info_opt.as_mut().unwrap(); - let mut task_miner_list: Vec> = Default::default(); - for miner_task in &deal_info.assigned_miner { - task_miner_list.push(miner_task.miner.clone()); - } - if task_miner_list.contains(&sender) { - if !deal_info.complete_list.contains(&sender) { - deal_info.complete_list.try_push(sender.clone()).map_err(|_| Error::::BoundedVecError)?; + + if !deal_info.complete_list.contains(&index) { + for task_info in &mut deal_info.miner_task_list { + if task_info.index == index { + match task_info.miner { + Some(_) => Err(Error::::Existed)?, + None => { + task_info.miner = Some(sender.clone()); + T::MinerControl::lock_space(&sender, task_info.fragment_list.len() as u128 * FRAGMENT_SIZE)?; + deal_info.complete_list.try_push(index).map_err(|_| Error::::BoundedVecError)?; + }, + }; + } else { + if let Some(miner) = &task_info.miner { + if miner == &sender { + Err(Error::::Existed)?; + } + }; + } } + + // If it is the last submitter of the order. - if deal_info.complete_list.len() == deal_info.assigned_miner.len() { + if deal_info.complete_list.len() == deal_info.miner_task_list.len() { deal_info.stage = 2; Self::generate_file( &deal_hash, deal_info.segment_list.clone(), - deal_info.assigned_miner.clone(), - deal_info.share_info.to_vec(), + deal_info.miner_task_list.clone(), deal_info.user.clone(), FileState::Calculate, deal_info.file_size, )?; let mut max_task_count = 0; - for miner_task in deal_info.assigned_miner.iter() { + for miner_task in deal_info.miner_task_list.iter() { let count = miner_task.fragment_list.len() as u128; if count > max_task_count { max_task_count = count; @@ -651,13 +661,14 @@ pub mod pallet { // Miners need to report the replaced documents themselves. // If a challenge is triggered before the report is completed temporarily, // these documents to be replaced also need to be verified - >::try_mutate(miner_task.miner.clone(), |pending_space| -> DispatchResult { - let replace_space = FRAGMENT_SIZE.checked_mul(count).ok_or(Error::::Overflow)?; - let pending_space_temp = pending_space.checked_add(replace_space).ok_or(Error::::Overflow)?; - *pending_space = pending_space_temp; - Ok(()) - })?; - Self::zero_task_failed_count(&miner_task.miner)?; + if let Some(miner) = &miner_task.miner { + >::try_mutate(miner, |pending_space| -> DispatchResult { + let replace_space = FRAGMENT_SIZE.checked_mul(count).ok_or(Error::::Overflow)?; + let pending_space_temp = pending_space.checked_add(replace_space).ok_or(Error::::Overflow)?; + *pending_space = pending_space_temp; + Ok(()) + })?; + } } let needed_space = Self::cal_file_size(deal_info.segment_list.len() as u128); T::StorageHandle::unlock_and_used_user_space(&deal_info.user.user, needed_space)?; @@ -708,7 +719,7 @@ pub mod pallet { let _ = ensure_root(origin)?; let deal_info = >::try_get(&deal_hash).map_err(|_| Error::::NonExistent)?; - for miner_task in deal_info.assigned_miner { + for miner_task in deal_info.miner_task_list { let count = miner_task.fragment_list.len() as u32; let mut hash_list: Vec> = Default::default(); for fragment_hash in miner_task.fragment_list { @@ -717,8 +728,9 @@ pub mod pallet { } // Accumulate the number of fragments stored by each miner let unlock_space = FRAGMENT_SIZE.checked_mul(count as u128).ok_or(Error::::Overflow)?; - T::MinerControl::unlock_space_to_service(&miner_task.miner, unlock_space)?; - T::MinerControl::insert_service_bloom(&miner_task.miner, hash_list)?; + let miner = miner_task.miner.ok_or(Error::::Unexpected)?; + T::MinerControl::unlock_space_to_service(&miner, unlock_space)?; + T::MinerControl::insert_service_bloom(&miner, hash_list)?; } >::try_mutate(&deal_hash, |file_opt| -> DispatchResult { diff --git a/c-pallets/file-bank/src/types.rs b/c-pallets/file-bank/src/types.rs index 6f544628..eb53eab4 100755 --- a/c-pallets/file-bank/src/types.rs +++ b/c-pallets/file-bank/src/types.rs @@ -19,7 +19,8 @@ pub struct SegmentList { #[scale_info(skip_type_params(T))] #[codec(mel_bound())] pub struct MinerTaskList { - pub(super) miner: AccountOf, + pub(super) index: u8, + pub(super) miner: Option>, pub(super) fragment_list: BoundedVec::MissionCount>, } @@ -41,11 +42,9 @@ pub struct DealInfo { pub(super) count: u8, pub(super) file_size: u128, pub(super) segment_list: BoundedVec, T::SegmentCount>, - pub(super) needed_list: BoundedVec, T::SegmentCount>, pub(super) user: UserBrief, - pub(super) assigned_miner: BoundedVec, ConstU32>, - pub(super) share_info: BoundedVec, T::SegmentCount>, - pub(super) complete_list: BoundedVec, T::FragmentCount>, + pub(super) miner_task_list: BoundedVec, ConstU32>, + pub(super) complete_list: BoundedVec, } //TODO! BoundedVec type -> BTreeMap diff --git a/c-pallets/sminer/src/lib.rs b/c-pallets/sminer/src/lib.rs index 2af4468c..e1887159 100644 --- a/c-pallets/sminer/src/lib.rs +++ b/c-pallets/sminer/src/lib.rs @@ -359,7 +359,7 @@ pub mod pallet { #[pallet::weight(Weight::zero())] pub fn register_pois_key( origin: OriginFor, - pois_key: PoISKey>, + pois_key: PoISKey, tee_sig: TeeRsaSignature ) -> DispatchResult { let sender = ensure_signed(origin)?; diff --git a/primitives/common/src/lib.rs b/primitives/common/src/lib.rs index 889016aa..f1220ea8 100644 --- a/primitives/common/src/lib.rs +++ b/primitives/common/src/lib.rs @@ -18,8 +18,7 @@ pub struct Hash(pub [u8; 64]); pub struct TryFromSliceError(()); #[derive(PartialEq, Eq, Encode, Decode, Clone, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct PoISKey { - pub acc: AccountId, +pub struct PoISKey { pub g: [u8; 256], pub n: [u8; 256], } @@ -29,7 +28,7 @@ pub struct SpaceProofInfo { pub miner: AccountId, pub front: u64, pub rear: u64, - pub pois_key: PoISKey, + pub pois_key: PoISKey, pub accumulator: Accumulator, }